Java 7 try-with-resources语法(也称为 ARM 块(自动资源管理))在仅使用一个AutoCloseable资源时非常好、简短且直接。但是,当我需要声明多个相互依赖的资源时,我不确定什么是正确的习惯用法,例如包装它的 aFileWriter和 a 。BufferedWriter当然,这个问题涉及AutoCloseable包装某些资源的任何情况,而不仅仅是这两个特定的类。
我想出了以下三个替代方案:
1)
我见过的幼稚习惯用法是仅在 ARM 管理的变量中声明顶级包装器:
static void printToFile1(String text, File file) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
这很好,很短,但它被打破了。因为底层FileWriter没有在变量中声明,所以它永远不会在生成的finally块中直接关闭。它只会通过closewrapping 的方法关闭BufferedWriter。bw问题是,如果从的构造函数中抛出异常,close则不会调用它,因此FileWriter 不会关闭底层。
2)
static void printToFile2(String text, File file) {
try (FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
在这里,底层资源和包装资源都声明在 ARM 管理的变量中,所以它们都肯定会被关闭,但底层fw.close() 会被调用两次:不仅直接调用,还通过 wrapping调用bw.close()。
对于这两个都实现的特定类Closeable(它是 的子类型AutoCloseable)来说,这应该不是问题,它们的合同规定close允许多次调用:
关闭此流并释放与其关联的任何系统资源。如果流已经关闭,则调用此方法无效。
但是,在一般情况下,我可以拥有仅实现AutoCloseable(而不是Closeable)的资源,这不能保证close可以多次调用:
请注意,与 java.io.Closeable 的 close 方法不同,此 close 方法不需要是幂等的。换句话说,多次调用此 close 方法可能会产生一些可见的副作用,这与 Closeable.close 不同,如果多次调用则要求无效。但是,强烈建议此接口的实现者使他们的 close 方法具有幂等性。
3)
static void printToFile3(String text, File file) {
try (FileWriter fw = new FileWriter(file)) {
BufferedWriter bw = new BufferedWriter(fw);
bw.write(text);
} catch (IOException ex) {
// handle ex
}
}
这个版本理论上应该是正确的,因为只有fw代表需要清理的真实资源。本身不持有任何资源,bw它只委托给fw,所以只关闭底层就足够了fw。
另一方面,语法有点不规则,而且 Eclipse 发出警告,我认为这是一个误报,但它仍然是一个必须处理的警告:
资源泄漏:'bw' 永远不会关闭
那么,该采用哪种方法呢?还是我错过了其他一些正确的成语?