最近在看代码的时候发现了IO流怎么都不需要自己手动关闭的呢,还以为是别人忘记关。结果一问,尴尬了。这居然是Java 7 的新特性。因此,特地的记录下来了。
try-with-resources,就是Java 7中的新特性之一。其本质是语法糖,在编译时会进行转化为 try-catch-finally 语句。编绎器自动在try-with-resources后面增加了判断对象是否为null,如果不为null,则调用close()函数的的字节码。
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(); } } 复制代码
这么一看起来,的确提高了可读性。
至于为什么要使用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接口就可以实现自动关闭资源的效果。
该语法的出现目的是让程序员不需要再编写繁琐的try-finally,并且还能提高代码的可读性。
无论有没有异常,都会首先执行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()); } } } 复制代码