转载

Java 7 Try-With-Resources

最近在看代码的时候发现了IO流怎么都不需要自己手动关闭的呢,还以为是别人忘记关。结果一问,尴尬了。这居然是Java 7 的新特性。因此,特地的记录下来了。

Java 7 Try-With-Resources

1. try-with-resources是什么来的?

try-with-resources,就是Java 7中的新特性之一。其本质是语法糖,在编译时会进行转化为 try-catch-finally 语句。编绎器自动在try-with-resources后面增加了判断对象是否为null,如果不为null,则调用close()函数的的字节码。

而且在try-with-resources中的变量必须实现AutoCloseable接口.

try-with-resources的语法:

// try-with-resources - the the best way to close resources!
static String firstLineOfFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(
           new FileReader(path))) {
       return br.readLine();
    }
}
复制代码

这么一看起来,的确提高了可读性。

2. 为什么要使用try-with-resources?

至于为什么要使用try-with-resources。可以看看try-finally使用的情况

在没有try-with-resources之前,这种语法最能确保关闭资源,无论是抛出异常还是返回。但是 可能会由于某些原因br.readLine()方法发生异常了,在这种情况下,close()方法调用也失败了,那么第一个异常会被第二个异常给冲掉,在异常跟踪栈中也找不到第一个异常的信息。这对于调试的时候来说是非常困难的。

static String firstLineOfFile(String path) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        br.close();
    }
}
复制代码

但如果在多个资源的情况下呢.变得难看了,不利于阅读了。

// try-finally is ugly when used with more than one resource!
static void copy(String src, String dst) throws IOException {
    InputStream in = new FileInputStream(src);
    try {
        OutputStream out = new FileOutputStream(dst);
        try {
            byte[] buf = new byte[BUFFER_SIZE];
            int n;
            while ((n = in.read(buf)) >= 0)
                out.write(buf, 0, n);
        } finally {
            out.close();
        }
    } finally {
        in.close();
    }
}
复制代码

正是由于以上的两个原因,try-with-resources出现了。他不需要程序员去管理繁琐的关闭资源,只需要在try-with-resources中的变量实现了AutoableColse接口就可以实现自动关闭资源的效果。

3. try-with-resources有什么好处?

该语法的出现目的是让程序员不需要再编写繁琐的try-finally,并且还能提高代码的可读性。

4. try-with-resources 处理异常?

无论有没有异常,都会首先执行close(),然后再判断是否需要进入catch块.

反编译后的代码:

public static void startTest() {
       try {
           MyAutoCloseA a = new MyAutoCloseA();
           Throwable var33 = null;

           try {
               MyAutoCloseB b = new MyAutoCloseB();
               Throwable var3 = null;

               try { // 我们定义的 try 块
                   a.test();
                   b.test();
               } catch (Throwable var28) { // try 块中抛出的异常
                   var3 = var28;
                   throw var28;
               } finally {
                   if (b != null) {
	                   // 如果 try 块中抛出异常,就将 close 中的异常(如果有)附加为压制异常
                       if (var3 != null) {
                           try {
                               b.close();
                           } catch (Throwable var27) {
                               var3.addSuppressed(var27);
                           }
                       } else { // 如果 try 块没有抛出异常,就直接关闭,可能会抛出关闭异常
                           b.close();
                       }
                   }

               }
           } catch (Throwable var30) {
               var33 = var30;
               throw var30;
           } finally {
               if (a != null) {
                   if (var33 != null) {
                       try {
                           a.close();
                       } catch (Throwable var26) {
                           var33.addSuppressed(var26);
                       }
                   } else {
                       a.close();
                   }
               }

           }
       // 所有的异常在这里交给 catch 块处理
       } catch (Exception var32) { // 我们定义的 catch 块
           System.out.println("Main: exception");
           System.out.println(var32.getMessage());
           Throwable[] suppressed = var32.getSuppressed();

           for(int i = 0; i < suppressed.length; ++i) {
               System.out.println(suppressed[i].getMessage());
           }
       }

   }
复制代码
原文  https://juejin.im/post/5bdc0ef951882516c22e4281
正文到此结束
Loading...