当前位置: 首页 > 知识库问答 >
问题:

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

王修为
2023-03-14

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

我可以想象自己写一些东西来做这件事,但是有没有类似于Python的Contextlib的现有实用程序。将关闭分配的资源的ExitStack?我希望它看起来像这样:

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

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

嘿,close投票者我不是在要求一个库,我是在问你如何安全地关闭动态数量的自动关闭的s,如果有语言功能,很好,如果有标准库函数,也很好,如果我必须自己写,很好。如果你想推荐一个常用的第三方库,里面有这个,那么一定要推荐。

共有3个答案

傅星光
2023-03-14

也许你可以这样做:

<T extends AutoCloseable> void recursively(
    List<T> things,
    Iterator<? extends Supplier<? extends T>> thingSuppliers,
    Consumer<List<T>> whenEmpty) {
  if (!thingSuppliers.hasNext()) {
    // No more to create. Pass all the things to the consumer.
    whenEmpty.accept(things);
    return;
  }

  // Create a new thing, and make a recursive call. This thing gets
  // closed as the stack unwinds.
  try (T thing = thingSuppliers.next().get()) {
    things.add(thing);
    recursively(things, thingSuppliers, whenEmpty);
  }
}

// Some means of starting the recursion.
<T extends AutoCloseable> void recursively(
    Iterable<? extends Supplier<? extends T>> thingSuppliers,
    Consumer<List<T>> whenEmpty) {
  recursively(new ArrayList<>(), thingSuppliers.iterator(), whenEmpty);
}

调用示例:

recursively(
    Arrays.asList(Widget::new, Widget::new), 
    System.out::println);
潘雅珺
2023-03-14

鉴于这个实用程序似乎不存在,我写了一个。它包装所有抛出的异常,然后仅在抛出资源的近()时抛出。总是在返回之前关闭所有东西。

public class ClosingException extends Exception { }

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<>();
}

并使用:

try (ClosingStack closingStack = new ClosingStack()) {
    List<Widget> widgets = new ArrayList<>();
    for (...) {
        widgets.add(closingStack.add(new Widget()));
    }
    // use widgets
}
詹钊
2023-03-14

我想你会发现番石榴的Closer课程正是你需要的:

try (Closer closer = Closer.create()) {
   InputStream in1 = closer.register(new FileInputStream("foo"));
   InputStream in2 = closer.register(new FileInputStream("bar"));
   // use in1 and in2
}
// in2 and in1 closed in that order

该课程仍被标记为Beta mind you,但似乎仍然存在。最初的目的是在不支持Java 7语言功能的情况下提供“资源试用”体验,但是一个有用的副作用是,它应该与动态数量的资源一起工作。

 类似资料:
  • 我想在我的编码中添加对话框。对话框可以弹出。假设用户按下ok按钮后对话框将关闭,但对话框将自动关闭。这是我的密码。有什么问题吗?

  • 我在windows 7中安装了android Studio,但它在打开后立即关闭。我还安装了java jdk并添加了一个JDK_HOME环境变量,但android Studio会在几秒钟后自行关闭。

  • 场景是:您在窗口(a)中,单击按钮/链接启动打印过程,然后打开一个新窗口(B),其中包含要打印的内容,打印对话立即显示,如果您单击窗口(B)的取消按钮,那么您应该可以再次打印,但当您单击窗口(B)的打印按钮打印时,您可以打印,但窗口(a)的按钮不能再次继续打印。给我一些解决方案…!!!在chrome,Firefox和internet explorer上工作

  • 问题内容: 我正在实现python-rq以在队列中传递域并使用Beautiful Soup对其进行抓取。因此,我正在雇用多名工人来完成工作。到目前为止,我已经开始了22位工作人员,所有22位工作人员都在rq仪表板中注册。但是一段时间后,工作人员会自行停下来,也不会显示在仪表板上。但是在webmin中,它将所有工作程序显示为正在运行。爬行速度也降低了,即工人没有在奔跑。我尝试使用主管和nohup运行

  • 关于这个问题,我已经做了相当多的谷歌搜索,我发现的大多数线程都有2年多的历史了,所以我想知道是否有什么改变,或者是否有一个新的方法来解决与这个话题有关的问题。 您在使用IntelliJ(我使用14.0.2)时可能知道,它经常自动保存文件。对我来说,在Java或JavaScript文件中进行更改时,大约需要2秒才能保存更改。有一些选项可能会对此产生影响,例如设置>外观和行为>系统设置>同步>如果应用