问题描述
给定一个 AutoCloseable
类 MyClass
,它在其构造函数中创建多个 SomeResource
类型的资源。 SomeResource
还实现了 AutoCloseable
,它的构造函数和它的 close
方法都可能抛出一个 IOException
。我如何最好地确保:
这是示例类:
public class MyClass implements AutoCloseable {
private final SomeResource resource1;
private final SomeResource resource2;
private final SomeResource resource3;
MyClass() throws IOException {
resource1 = new SomeResource();
resource2 = new SomeResource();
resource3 = new SomeResource();
}
@Override public void close() throws IOException {
resource1.close();
resource2.close();
resource3.close();
}
}
解决方法
a) 构造函数不能使用 try-with-resources 或 try-finally,因为如果资源可以成功创建,则不应关闭资源。相反,资源的创建应该跟在一个 try-catch 块之后,以确保资源在其创建后出现任何错误时关闭。在 catch 块中,必须重新抛出异常,以免丢失。
b) close 方法可以使用 try-with-resource 块来确保关闭所有资源
public class MyClass implements AutoCloseable {
private final SomeResource resource1;
private final SomeResource resource2;
private final SomeResource resource3;
MyClass() throws IOException {
resource1 = new SomeResource();
try {
resource2 = new SomeResource();
try {
resource3 = new SomeResource();
} catch (IOException | RuntimeException e) {
closeIgnoreException(resource2);
throw e;
}
} catch (IOException | RuntimeException e) {
closeIgnoreException(resource1);
throw e;
}
}
private static void closeIgnoreException(AutoCloseable autoCloseable) {
try { autoCloseable.close(); } catch (Exception ignore) {}
}
@Override
public void close() throws IOException {
try (resource1;
resource2;
resource3) {}
}
}
在 Java 9 之前,try-with-resources 语句不接受任何引用。因此,close
方法必须通过以下方式实现:
public void close() throws IOException {
try (SomeResource r1 = resource1;
SomeResource r2 = resource2;
SomeResource r3 = resource3) {}
}