try
- with-resources很好,所有这一切,但在我看来,在创建包装多个AutoCloseable
对象的类时,仍然不足以进行有效的资源管理。例如,考虑
import java.io.*;
class AutocloseableWrapper implements AutoCloseable {
private FileReader r1;
private FileReader r2;
public AutocloseableWrapper(String path1, String path2) throws IOException {
r1 = new FileReader(path1);
r2 = new FileReader(path2);
}
@Override
public void close() throws IOException {
r1.close();
r2.close();
}
public static void main(String[] args) throws IOException {
try (AutocloseableWrapper w = new AutocloseableWrapper("good-path", "bad-path")) {
System.out.format("doing something\n");
throw new IOException("doing something in main");
}
}
}
此包装器至少存在两个问题:
r2
投降,则r1
未关闭。r1.close
抛出,则r2
未关闭。所有这些问题都可以解决,但是编写包装器变得非常重要且容易出错,即使只包装了两个资源:
import java.io.*;
class AutocloseableWrapper implements AutoCloseable {
private FileReader r1;
private FileReader r2;
public AutocloseableWrapper(String path1, String path2) throws IOException {
r1 = new FileReader(path1);
try {
r2 = new FileReader(path2);
}
catch (IOException e) {
try {
r1.close();
}
catch (IOException e2) {
e.addSuppressed(e2);
}
throw e;
}
}
@Override
public void close() throws IOException {
IOException e = null;
try {
r1.close();
}
catch (IOException e1) {
e = e1;
}
try {
r2.close();
}
catch (IOException e2) {
if (e == null)
throw e2;
else {
e.addSuppressed(e2);
throw e;
}
}
}
public static void main(String[] args) throws IOException {
try (AutocloseableWrapper w = new AutocloseableWrapper("good-path", "bad-path")) {
System.out.format("doing something\n");
throw new IOException("doing something in main");
}
}
}
是否有一些帮助程序类或任何其他方法使编写包装器更容易?
答案 0 :(得分:2)
你应该启用编译器解包的语法代码....你可以在这里找到Oracle文章: - http://www.oracle.com/technetwork/articles/java/trywithresources-401775.html
提出问题,如果你有一个包装器,你可以做这样的事情
@Override
public void close() throws IOException {
Throwable t = null;
try {
r1.close();
} catch (Throwable t1) {
t = t1;
throw t1;
} finally {
if (t != null) {
try {
r2.close();
} catch (Throwable t2) {
t.addSuppressed(t2);
}
} else {
r2.close();
}
}
}
注意:由于Java中的精确重新抛出功能 7
,这将起作用答案 1 :(得分:1)
您可以使用通用资源包装器,例如:
public class CloseableChain implements AutoCloseable {
private AutoCloseable r1;
private CloseableChain r2;
public void attach(AutoCloseable r) {
if (r1 == null) {
r1 = r;
} else {
if (r2 == null) {
r2 = new CloseableChain();
}
r2.attach(r);
}
}
public void close() throws Exception {
if (r1 == null) {
return;
}
Throwable t = null;
try {
r1.close();
} catch (Throwable t1) {
t = t1;
throw t1;
} finally {
if (r2 != null) {
if (t != null) {
try {
r2.close();
} catch (Throwable t2) {
t.addSuppressed(t2);
}
} else {
r2.close();
}
}}}}
然后你可以将你的代码重构为:
import java.io.*;
class AutocloseableWrapper implements AutoCloseable {
private CloseableChain chain;
private FileReader r1;
private FileReader r2;
private FileReader r3;
public AutocloseableWrapper(String path1, String path2) throws IOException {
chain = new CloseableChain();
r1 = new FileReader(path1);
chain.attach(r1);
r2 = new FileReader(path2);
chain.attach(r2);
// and even more...
r3 = new FileReader("whatever");
chain.attach(r3);
}
@Override
public void close() throws IOException {
chain.close();
}
public static void main(String[] args) throws IOException {
try (AutocloseableWrapper w = new AutocloseableWrapper("good", "bad")) {
System.out.format("doing something\n");
throw new IOException("doing something in main");
}
}
}