11

Autocloseable应始终与try-with-resources. 至少 Intellij 检查表明了这一点。因此,如果我有一个生成Foo该实现的代码,Autocloseable我应该这样做:

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

但是如果我有返回的函数Foo[]呢?或者接受Foo[](或Collection<Foo>)作为其参数的函数?

我该如何使用它try-with-resources?查看以下函数:

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

我想做点事doAll(getFoos())

我怎样才能做到这一点?

4

3 回答 3

7

Try-with-resources 语句只能关闭那些在其标头中声明和分配的资源。因此,唯一的方法是使您获得的 Collection 实现 AutoCloseable 或将其包装到您的 AutoCloseable 扩展中,因此其 close() 方法将由 TWR 调用。喜欢:

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

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


如果您要自己关闭集合,可以查看Apache Drill项目和课程org.apache.drill.common.AutoCloseables- 它就是这样做的,它自己关闭了许多 AutoCloseables。

于 2016-12-07T12:40:26.990 回答
6

您可以创建将AutoCloseables 组合为一个的方法,该方法将安全地关闭所有这些方法:

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
    */
}
于 2016-12-07T13:41:20.567 回答
1

正如另一个答案所述,这实际上是不可能的。但是,您应该问自己为什么需要将整个集合放在 AutoCloseable 中。如果您想确保每个元素在处理后关闭,您可以执行以下操作:

Foo[] foos = getFoos();
for (int i = 0; i < foos.length; i++) {
  try (Foo foo = foos[i]) {
    // Your code here
  }
}
于 2016-12-07T13:02:17.393 回答