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
块中直接关闭。它只会通过close
wrapping 的方法关闭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' 永远不会关闭
那么,该采用哪种方法呢?还是我错过了其他一些正确的成语?