仅使用一种资源时,Java 7 try-with-resources语法(也称为ARM块(自动资源管理))非常好,简短而直接AutoCloseable
。但是,当我需要声明相互依赖的多个资源时(例如a FileWriter
和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
包装方法将其关闭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()
将被调用两次:不仅直接调用,而且还通过包装调用bw.close()
。
对于这两个都实现的特定类Closeable
(这是的子类型AutoCloseable
),这应该不是问题,它们的协定规定close
允许多次调用:
关闭此流并释放与其关联的所有系统资源。如果流已经关闭,则调用此方法无效。
但是,在一般情况下,我可以拥有仅实现AutoCloseable
(而不是Closeable
)实现的资源,这不能保证close
可以多次调用:
请注意,与java.io.Closeable的close方法不同,该close方法不需要是幂等的。换句话说,多次调用此close方法可能会产生一些可见的副作用,这与Closeable.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”从未关闭
那么,该采用哪种方法?还是我错过了其他正确的成语?
public BufferedWriter(Writer out, int sz)
可以抛出一个IllegalArgumentException
。另外,我可以使用一个类扩展BufferedWriter,该类将从其构造函数中抛出某些内容或创建我需要的任何自定义包装器。
BufferedWriter
构造可以很容易地抛出异常。OutOfMemoryError
可能是最常见的一种,因为它为缓冲区分配了相当大的内存(尽管可能表明您想重新启动整个过程)。/你需要flush
你的BufferedWriter
,如果你不关闭并希望保留的内容(一般只非例外情况)。FileWriter
选取碰巧是“默认”文件编码的任何东西-最好是明确的。