try-with-resources 優先于try-finally
我們一般在關閉資源的時候都會選用try-finally,比如關閉各種讀寫流,資料庫連接配接對象等,都會在finally中調用對象的close方法,即使發生異常也會確定資源被釋放,這看上去沒有什麼問題。
但是再添加另一個資源,就會顯的亂七八糟的感覺,如下是檔案拷貝代碼示例。
public 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[1024];
int n;
while ((n = in.read(buf)) >= 0) {
out.write(buf,0,n);
}
} finally {
out.close();
}
} finally {
in.close();
}
}在這裡插入代碼片
在上面的代碼示例中有兩個缺點
1.關閉的資源多了,try-finally就嵌套的多了,代碼感覺很亂。
2.try和finally中都會抛出異常,如果底層實體裝置異常,那麼try中流在讀檔案的過程中就會有異常,同樣finally中流close的時候也會發生異常,這種情況下,close中的異常就會覆寫try中的異常,try中的異常甚至都沒有列印出錯誤堆棧,顯然try中的異常才是對我們有價值的異常。
是以為了避免上述的問題,我們應該使用java7中引用的try-with-resource語句,上面的兩個問題就不會存在了,要關閉資源的類必須實作AutoCloseable接口,包含無傳回值的close方法,現在java中的很多類庫都實作了這個接口。
public static void copy(String src, String dst) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);) {
byte[] buf = new byte[1024];
int n;
while ((n = in.read(buf)) >= 0) {
out.write(buf, 0, n);
}
}
}
現在第一個代碼就變成了這樣,将要關閉的資源放在了try後面的括号裡面,自己就會在用完的時候釋放資源,而且如果發生異常也是會列印出第一個異常,close裡面的異常就會被禁止,我們就可以找到對我們有用的異常。
結論
結論很明顯: 在處理必須關閉的資源時,始終要優先考慮用try- with-resources ,而不是
用try-finally 。這樣得到的代碼将更加簡潔、清晰,産生的異常也更有價值。有了trywith-
resources 語句,在使用必須關閉的資源時,就能更輕松地正确編寫代碼了。實踐證明,
這個用try-finally 是不可能做到的。