What is the best way to emulate try-with-resources in Java 6?

本小妞迷上赌 提交于 2019-12-19 17:04:09

问题


It turns out that almost nobody closes resources in Java correctly. Programmers either do not use try-finally block at all, or just put resource.close() in finally which is also incorrect (because Throwable from close() can shadow Throwable from try block). Sometimes they put something like IOUtils.closeQuietly() with is only correct for InputStream, but not for OutputStream. try-with-resources solves all of these problems but there are still huge number of projects written in Java 6.

What is the best way to emulate try-with-resources in Java 6? Now I use Guava Closer, which is better than nothing but still much uglier than try-with-resources. Also, there is a pattern called a loan-pattern, but the absence of lambdas in Java makes this pattern very cumbersome. Is there a better way?


回答1:


I've found a good replacement for try-with-resources. It uses Lombok library with annotation processing:

 @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);
 }

However, it doesn't handle exception correctly. This bug is more than 1 year old and still is not closed: https://code.google.com/p/projectlombok/issues/detail?id=384




回答2:


Though anonymous class is quite verbose, it's still acceptable in java land

    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
    }
}



回答3:


If your only problem with IOUtils.closeQuietly is that it ignores exceptions on OutputStreams, then you can either simply call close() on them, or create your own utility class which automatically treats the two differently, like this:

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();
}

The correct overloaded method will be selected at compile time in all common situations, although if you're passing OutputStreams around as Closeables then you'll have to change this to do a dynamic instanceof check to make sure OutputStreams always throw exceptions.



来源:https://stackoverflow.com/questions/19497532/what-is-the-best-way-to-emulate-try-with-resources-in-java-6

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!