【发布时间】:2026-02-09 13:45:01
【问题描述】:
这个程序:
import java.util.*;
public class Main {
static Set<String> openResources = new TreeSet<>();
static class MyResource implements AutoCloseable {
boolean close;
MyResource encapsulatedResource;
String name;
MyResource(String id, boolean exceptionOnCreate, boolean exceptionOnClose, MyResource encapsulatedResource) {
this.close = exceptionOnClose;
this.encapsulatedResource = encapsulatedResource;
this.name = id;
if (exceptionOnCreate) {
throw new RuntimeException("Exception when creating " + id);
}
openResources.add(id);
System.out.println(name + " is now open");
}
@Override
public void close() {
if (close) {
throw new RuntimeException("Exception when closing " + name);
}
if (encapsulatedResource != null) {
encapsulatedResource.close();
}
openResources.remove(name);
System.out.println(name + " was successfully closed");
}
}
public static void main(String[] args) {
try (AutoCloseable resource1 = new MyResource("resource1", false, false, null);
MyResource resource2 = new MyResource("resource2", false, true, null);
AutoCloseable resource3 = new MyResource("resource3", false, false, resource2);
AutoCloseable resource4 = new MyResource("resource4", true, false, null);) {
System.out.println("main program");
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println("openResources: " + openResources);
}
}
有以下输出:
resource1 is now open
resource2 is now open
resource3 is now open
resource1 was successfully closed
Exception when creating resource4
openResources: [resource2, resource3]
我希望在使用 try-with-resources 时所有资源都已正确关闭,并且我不会有任何泄漏。但是,在这里,资源 2 和 3 被泄露。为什么?我不能依赖那个语法吗?
【问题讨论】:
-
这与 try-catch 的“可靠性”无关,而与您连接资源的方式以及它们抛出异常的事实有关。关闭resource3会在尝试关闭封装的resource2时抛出异常。关闭resource2会抛出异常。
-
是的,您创建的示例确实存在如上所述的缺陷。