在 try-with-resources 中关闭动态数量的 AutoCloseable 对象

Rya*_*ing 7 java java-8 try-with-resources autocloseable

AutoCloseable我正在一个块中创建可变数量的对象try-with-resources。在任何退出点,我都希望关闭所有分配的资源。

我可以想象自己写一些东西来做到这一点,但是是否有一个类似于Python 的 contextlib.ExitStack 的现有实用程序可以关闭分配的资源?我希望它看起来像这样:

try (ExitStack exitStack = new ExitStack()) {
    List<Widget> widgets = new ArrayList<>();
    for (...) {
        widgets.add(exitStack.add(new Widget()));
    }
    // use widgets
}
Run Code Online (Sandbox Code Playgroud)

(注意:这不是这个问题,因为我不知道我会提前拥有多少资源。

嘿,亲密的选民,我不是在要求一个库,我是在问你如何完成安全关闭动态数量的任务AutoCloseable,如果有一个语言功能,那就太好了,如果有一个标准库函数,也很棒,如果我必须自己写,那很好。如果您推荐一个常用的包含此内容的第三方库,那么当然可以。

Rya*_*ing 3

鉴于这个实用程序似乎不存在,我编写了一个。它包装所有抛出的异常,然后仅在资源的 close() 抛出时抛出。返回之前始终关闭所有内容。

public class ClosingException extends Exception { }
Run Code Online (Sandbox Code Playgroud)

import java.util.Deque;
import java.util.ArrayDeque;

public final class ClosingStack implements AutoCloseable {
  public void close() throws ClosingException {
    ClosingException allClosingExceptions = new ClosingException();
    while (!resources.isEmpty()) {
      try {
        resources.removeLast().close();
      } catch (Throwable e) {
        allClosingExceptions.addSuppressed(e);
      }
    }
    if (allClosingExceptions.getSuppressed().length != 0) {
      throw allClosingExceptions;
    }
  }

  public <T extends AutoCloseable> T add(T resource) {
    resources.addLast(resource);
    return resource;
  }


  private Deque<AutoCloseable> resources = new ArrayDeque<>();
}
Run Code Online (Sandbox Code Playgroud)

并使用:

try (ClosingStack closingStack = new ClosingStack()) {
    List<Widget> widgets = new ArrayList<>();
    for (...) {
        widgets.add(closingStack.add(new Widget()));
    }
    // use widgets
}
Run Code Online (Sandbox Code Playgroud)

  • @Thomas:您认为可以节省哪些资源?在实践中,ArrayDeques 几乎在所有方面都更便宜。 (5认同)