事实证明,几乎没有人正确地关闭Java中的资源。程序员根本不使用try-finally
阻止,或只是将resource.close()
放在finally
中,这也是不正确的(因为来自Throwable
的{{1}}可能会影响{{1}来自try block)。有时他们会将close()
之类的内容与Throwable
相匹配,但不适用于IOUtils.closeQuietly()
。 InputStream
解决了所有这些问题,但仍然有大量的项目用Java 6编写。
在Java 6中模拟OutputStream
的最佳方法是什么?现在我使用Guava Closer,这比没有任何东西好,但仍然比try-with-resources
更丑。此外,还有一种称为贷款模式的模式,但Java中缺少lambdas使得这种模式非常麻烦。还有更好的方法吗?
答案 0 :(得分:3)
我找到了try-with-resources
的替代品。它使用带有注释处理的Lombok库:
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
但是,它没有正确处理异常。此错误已超过1年,仍未关闭:https://code.google.com/p/projectlombok/issues/detail?id=384
答案 1 :(得分:0)
虽然匿名类非常详细,但在java版本中它仍然可以接受
new TryWithResource<InputStream>(){
protected InputStream init() throws Exception {
return new FileInputStream("abc.txt");
}
protected void use(InputStream input) throws Exception{
input.read();
}
};
----
abstract class TryWithResource<R>
{
abstract protected R init() throws Exception;
abstract protected void use(R resource) throws Exception;
// caution: invoking virtual methods in constructor!
TryWithResource() throws Exception
{
// ... code before
R r = init();
use(r);
// ... code after
}
}
答案 2 :(得分:0)
如果IOUtils.closeQuietly
的唯一问题是它忽略了OutputStreams上的异常,那么你可以简单地在它们上面调用close()
,或者创建你自己的实用程序类,它会自动处理两者,就像这样:
public static void close(Closeable resource)
{
try
{
resource.close();
}
catch(Exception e)
{
//swallow exception
}
}
public static void close(OutputStream o)
{
//throw any exceptions
o.close();
}
在所有常见情况下,将在编译时选择正确的重载方法,但如果您将OutputStream
作为Closeable
传递,那么您必须更改此方法以进行动态处理instanceof
检查以确保OutputStream
始终抛出异常。