[英]Close a dynamic number of AutoCloseable objects in try-with-resources
I am creating a variable amount of AutoCloseable
objects in a try-with-resources
block.我正在try-with-resources
块中创建可变数量的AutoCloseable
对象。 At any point of exit, I want all of the allocated resources closed.在任何退出点,我都希望关闭所有分配的资源。
I can imagine writing something myself to do this, but is there an existing utility similar to Python's contextlib.ExitStack that will close allocated resources?我可以想象自己编写一些东西来做到这一点,但是是否有类似于Python 的 contextlib.ExitStack的现有实用程序可以关闭分配的资源? I would expect it to look like this:我希望它看起来像这样:
try (ExitStack exitStack = new ExitStack()) {
List<Widget> widgets = new ArrayList<>();
for (...) {
widgets.add(exitStack.add(new Widget()));
}
// use widgets
}
(Note: this is not this question because I don't know how many resources I'll have ahead of time. (注意:这不是这个问题,因为我不知道我会提前拥有多少资源。
Hey close voters I'm not asking for a library, I'm asking how you would accomplish the task of safely closing a dynamic number of AutoCloseable
s, if there's a language feature for it, great, if there's a standard library function, also great, if I have to write my own, fine.嘿亲密的选民,我不是要图书馆,我是问你如何完成安全关闭动态数量的AutoCloseable
的任务,如果有语言功能,很好,如果有标准库功能,还有太好了,如果我必须自己写,那很好。 If you'd like to recommend a third-party library in common use that has this in it then sure.如果您想推荐的是,在它的话,当然有这个共同使用一个第三方库。
Given that this utility does not appear to exist, I wrote one.鉴于此实用程序似乎不存在,我写了一个。 It wraps up any thrown exceptions and then only throws if a resource's close() threw.它包含任何抛出的异常,然后仅在资源的 close() 抛出时抛出。 Always closes everything before returning.在返回之前总是关闭所有东西。
public class ClosingException extends Exception { }
And和
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<>();
}
And use:并使用:
try (ClosingStack closingStack = new ClosingStack()) {
List<Widget> widgets = new ArrayList<>();
for (...) {
widgets.add(closingStack.add(new Widget()));
}
// use widgets
}
I think you'll find Guava's Closer
class to be what you need here:我想你会发现 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
The class is still marked as Beta mind you, but has appeared to stick around.请注意,该课程仍被标记为 Beta,但似乎一直存在。 The original intent was to provide a try-with-resources experience without Java 7 language feature support, however a useful side effect is that it should work with a dynamic number of resources.最初的目的是在没有 Java 7 语言特性支持的情况下提供一种尝试资源的体验,但是一个有用的副作用是它应该使用动态数量的资源。
Perhaps you could do something like this:也许你可以这样做:
<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);
}
Example invocation:示例调用:
recursively(
Arrays.asList(Widget::new, Widget::new),
System.out::println);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.