2016-12-07 45 views
4

Autocloseable应始终与try-with-resources一起使用。至少Intellij检查表明它。 所以,如果我有一个产生Foo实现Autocloseable我应该做的代码:Java8中的“Autocloseable”的数组或集合

try (final Foo foo = getFoo()) { 
    foo.doSomething(); 
} 

但如果我有函数,返回Foo[]?或接受Foo[](或Collection<Foo>)作为参数的函数?如何使用try-with-resources? 着眼于以下功能:

Foo[] getFoos(); 
doAll(Foo... foo); 

我想要做的事行doAll(getFoos())

我怎么能这样做?

回答

4

Try-with-resources语句只能关闭在头文件中声明并分配的资源。所以唯一的方法是让你正在收集的Collection实现AutoCloseable或者将它包装到你的AutoCloseable扩展中,所以它的close()方法将被T-W-R调用。像:

try (SomeAutoCloseableCollction col = getAutoCloseables()) { 
     System.out.println("work"); 
} //col.close() gets called 

对于一个数组,恐怕没有办法,因为你不能扩展它并使它实现一些接口。


如果你自己收集,可看Apache Drill项目和org.apache.drill.common.AutoCloseables类 - 它正是这么做的,其本身关闭大量AutoCloseables的。

1

正如其他答案指出,这是不可能的。但是,您应该问自己为什么需要将整个集合放入AutoCloseable中。如果你想确保每个元素都被处理后关闭,你可以这样做:

Foo[] foos = getFoos(); 
for (int i = 0; i < foos.length; i++) { 
    try (Foo foo = foos[i]) { 
    // Your code here 
    } 
} 
+0

我无法找到一种方法,使与增强的for循环这项工作,但如果真有人看到的方式,请更新我的编辑答案。 –

+4

你的意思是for(Foo foo:getFoos())try(Foo toClose = foo){/ * code * /}'?这应该工作。 – Holger

3

您可以创建AutoCloseable小号合并到一个单一的一个方法,将安全地关闭所有的人:

public static AutoCloseable closeBoth(AutoCloseable a, AutoCloseable b) { 
    if(a==null) return b; 
    if(b==null) return a; 
    return() -> { try(AutoCloseable first=a) { b.close(); } }; 
} 
public static AutoCloseable closeAll(AutoCloseable... c) { 
    return Arrays.stream(c).reduce(null, MyClass::closeBoth); 
} 

它们允许使用数组返回方法类似

Foo[] foo; 
try(AutoCloseable closeAll = MyClass.closeAll(foo=getFoos())) { 
    /* 
     use foo 
    */ 
}