在Java 6中模拟try-with-resources的最佳方法是什么?

时间:2013-10-21 14:41:25

标签: java try-with-resources

事实证明,几乎没有人正确地关闭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使得这种模式非常麻烦。还有更好的方法吗?

3 个答案:

答案 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始终抛出异常。