JDK7的try-with-resource方式的使用

如果使用傳統try-catch-finally管理資源鏈接,代碼可能是下面這樣,finally代碼遠遠多於業務代碼。
這裏寫圖片描述
爲了增加代碼可讀性和可維護性,建議使用jdk7 提供的新特性try-with-resource(只能在表面上省去finally塊關閉資源的邏輯):
這裏寫圖片描述
即:try(資源定義){
業務邏輯
}
其實這只是個語法糖,因爲編譯時編譯器會自動幫代碼加上finally並調用close方法(前提是這些資源類都實現了Closeable接口)。(將你編譯好的.class文件拖入idea即可看到編譯後的代碼(idea可以反編譯出來))
這裏寫圖片描述
可以看出finally代碼塊中除了正常關閉連接代碼外,還包含了addSuppressed()方法,這個方法作用是保證一個異常不被另外一個異常抑制而無法拋出,比如try-catch塊代碼拋異常,程序會繼續執行finally代碼,但如果finally代碼又拋錯,就會導致try-catch的異常無法正常拋出,此時可以使用addSuppressed()方法可以將被抑制的異常也拋出。
參考鏈接:https://my.oschina.net/fhd/blog/324484
try-with-resource代碼確實好用,程序可讀性有所提高。但看着上面第二張圖片的代碼,你是否懷疑資源最大可能被關閉?是否編譯器加上的fin.close()方法和out.close()方法就完整了?不是的。請看GZIPOutputStream類的close()方法
下面是GZIPOutputStream類的父類的close()方法(GZIPOutputStream類沒重寫)
這裏寫圖片描述
close()方法時先調用finish()方法再調用out.close()方法,所以如果finish()方法順利執行,那麼out.close()方法確實可以順利執行。
但進去finish()方法看看,
這裏寫圖片描述
finish()方法是聲明瞭會拋異常的,也就是finish()方法不見得一定正常執行,也就導致了out.close()方法在finish()方法拋異常時不能被調用,進而導致資源沒有被關閉。
對於各個資源類的包裝類,內部都是使用裝飾者模式實現的,例子中調用out.close()方法,深層次還是調用FileOutputStream類的close方法,既然這樣,我們程序就應該最大程度確保最內層資源的close()方法被調用(就算包裝類的close()方法拋異常),才能最大程度上保證資源被關閉。
因此上面try-with-resource例子的流嵌套是不合理的,應該使用下面這種方式(分開定義每個Closeable類的資源):
這裏寫圖片描述
看上面分開定義後編譯生成的代碼(如下):
這裏寫圖片描述
顯然,每一層Closeable類的資源的close()方法都被顯式地調用。保證了資源最大程度的關閉。

發佈了109 篇原創文章 · 獲贊 130 · 訪問量 44萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章