Java7的try-with-resources宣告(轉)
阿新 • • 發佈:2020-08-23
看《Effective Java》第三版的時候,看到了其中建議將try-finally
替換為try-with-resources
。這個語法糖還算有意思,特此成文。
用法辨析
Java庫中有很多資源需要手動關閉,比如InputStream、OutputStream、java.sql.Connection等等。在此之前,通常是使用try-finally
的方式關閉資源;Java7之後,推出了try-with-resources
宣告來替代之前的方式。 try-with-resources
宣告要求其中定義的變數實現 AutoCloseable 介面,這樣系統可以自動呼叫它們的close方法,從而替代了finally中關閉資源的功能。
舉個栗子,下面是一個複製檔案的方法,按照原本try-catch-finally
的寫法:
// 一個簡單的複製檔案方法。 public static void copy(String src, String dst) { InputStream in = null; OutputStream out = null; try { in = new FileInputStream(src); out = new FileOutputStream(dst); byte[] buff = new byte[1024];int n; while ((n = in.read(buff)) >= 0) { out.write(buff, 0, n); } } catch (IOException e) { e.printStackTrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } }if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } }
可以看出,這種實現非常的醜陋。
下面來看使用了try-with-resources
後的效果:
public static void copy(String src, String dst) { try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst)) { byte[] buff = new byte[1024]; int n; while ((n = in.read(buff)) >= 0) { out.write(buff, 0, n); } } catch (IOException e) { e.printStackTrace(); } }
try-with-resources
將會自動關閉try()
中的資源,並且將先關閉後宣告的資源。
如果不catch IOException就更加清爽了:
public static void copy(String src, String dst) throws IOException { try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst)) { byte[] buff = new byte[1024]; int n; while ((n = in.read(buff)) >= 0) { out.write(buff, 0, n); } } }
原理分析
那麼try-with-resources
有什麼神奇之處呢?到底做了什麼呢?
我們先來看下AutoCloseable
介面:
public interface AutoCloseable { void close() throws Exception; }
其中僅有一個close方法,實現AutoCloseable介面的類將在close方法中實現其關閉資源的功能。
而try-with-resources
其實是個語法糖,它將在編譯時編譯成關閉資源的程式碼。我們將上述例子中的程式碼編譯成class檔案,再反編譯回java檔案,就能看到如下程式碼
public static void copy(String var0, String var1) throws IOException { FileInputStream var2 = new FileInputStream(var0); Throwable var3 = null; try { FileOutputStream var4 = new FileOutputStream(var1); Throwable var5 = null; try { byte[] var6 = new byte[1024]; int var7; while((var7 = var2.read(var6)) >= 0) { var4.write(var6, 0, var7); } } catch (Throwable var29) { var5 = var29; throw var29; } finally { if (var4 != null) { if (var5 != null) { try { // 關閉FileOutputStream var4.close(); } catch (Throwable var28) { var5.addSuppressed(var28); } } else { var4.close(); } } } } catch (Throwable var31) { var3 = var31; throw var31; } finally { if (var2 != null) { if (var3 != null) { try { // 關閉FileInputStream var2.close(); } catch (Throwable var27) { var3.addSuppressed(var27); } } else { var2.close(); } } } }
除卻處理異常相關的程式碼,其實就是呼叫了資源的close方法。
不過不得不說這個語法糖挺甜,真香。