我正在try-with-resources
块中创建可变数量的try (ExitStack exitStack = new ExitStack()) {
List<Widget> widgets = new ArrayList<>();
for (...) {
widgets.add(exitStack.add(new Widget()));
}
// use widgets
}
对象。在任何出口,我都希望所有分配的资源都关闭。
我可以想象自己写点东西来做到这一点,但是是否存在类似于Python's contextlib.ExitStack的现有实用程序将关闭分配的资源?我希望它看起来像这样:
AutoCloseable
(注意:这不是this question,因为我不知道我会提前拥有多少资源。
嘿,亲密的选民,我不是要图书馆,而是要问您如何完成安全sub $t0,$s3,$s4
add $t0,$s6,$t0
lw $t1,16($t0)
sw $t1,32($s7)
个动态关闭的任务(如果有语言)它的功能很棒,如果有标准的库函数,也很棒,如果我必须自己编写的话,也很好。如果您想喜欢推荐一个常用的第三方库,请确保该库。
答案 0 :(得分:1)
鉴于此实用程序似乎不存在,我写了一个。它包装所有抛出的异常,然后仅在抛出资源的close()时抛出。返回之前总是关闭所有内容。
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
}
答案 1 :(得分:1)
我想您会在这里找到Guava的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,请注意。最初的目的是在没有Java 7语言功能支持的情况下提供尝试资源的体验,但是一个有用的副作用是它应该使用动态数量的资源。
答案 2 :(得分:0)
也许您可以执行以下操作:
<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);