若是使用傳統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()方法都被顯式地調用。保證了資源最大程度的關閉。ide