說到j(luò)ava.io.Closeable接口就避不開java.lang.AutoCloseable接口,因為在java版本7.0時引入了java.lang.AutoCloseable接口,同時java.io.Closeable接口便繼承自java.lang.AutoCloseable接口了。
java.io.Closeable
先說一下Closeable接口,這個接口從java 5.0版本開始引入,其中中僅聲明了一個方法close,用于關(guān)閉一個資源。一直一來我都很困惑,就算不實現(xiàn)這個接口,我給我的類實現(xiàn)一個close方法(或者別的方法)來完成“關(guān)閉”的功能不也是一樣的么。直到我看到下面的兩段代碼。
//第一段代碼
static void copy(String src, String dest)throws IOException {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte[] buf = new byte[1024];
int n;
while ((n = in.read(buf)) >= 0) {
out.write(buf, 0, n);
}
} finally {
if (in != null) in.close();
if (out != null) out.close();
}
}
上面這段代碼的問題在于,finally語句中的close方法也可能會拋出IOException異常。如果這正好發(fā)現(xiàn)在in.close被調(diào)用之時,那么這個異常就會阻止out.close被調(diào)用,從而使輸出流保持在打開狀態(tài)。所以這個程序使得finally可能被意外結(jié)束。解決方式是將每一個close都包裝在一個try語句塊中。從java 5.0版本開始,可以利用Closeable接口。
//第二段代碼
// 對第一段代碼中的finally語句改造如下
finally {
closeIgnoringIOException(in);
closeIgnoringIOException(out);
}
private static void closeIgnoringIOException(Closeable c) {
if (c != null) {
try {
c.close();
} catch (IOException ex) { }
}
}
基于以上兩段代碼我知道了java.io.Closeable接口的用處。
java.lang.AutoCloseable
在java 7.0j時引入了java.lang.AutoCloseable,并且java.io.Closeable接口繼承自 java.lang.AutoCloseable。很多資源類都直接或間接的實現(xiàn)了此接口。其實這個接口與try-with-resources語法是密切相關(guān)的。
從AutoCloseable的注釋可知它的出現(xiàn)是為了更好的管理資源,準(zhǔn)確說是資源的釋放,當(dāng)一個資源類實現(xiàn)了該接口close方法,在使用try-with-resources語法創(chuàng)建的資源拋出異常后,JVM會自動調(diào)用close 方法進(jìn)行資源釋放,當(dāng)沒有拋出異常正常退出try-block時候也會調(diào)用close方法。
//第三段代碼
static void copy(String src, String dest)throws IOException {
try (InputStream in=new FileInputStream(src);OutputStream out=new FileOutputStream(dest)){
byte[] buf = new byte[1024];
int n;
while ((n = in.read(buf)) >= 0) {
out.write(buf, 0, n);
}
}catch(Exception e) {
System.out.println("catch block:"+e.getLocalizedMessage());
}finally{
System.out.println("finally block");
}
}
因為InputStream和OutputStream都實現(xiàn)了java.io.Closeable接口(間接實現(xiàn)了java.lang.AutoCloseable接口)所以上面的【第三段代碼】與【第二段代碼的】一樣“安全”。
try-with-resources
try-with-resources 是在java 7.0 版本時引入的新語法特性。使用它配合java.lang.AutoCloseable接口可以更好的對資源進(jìn)行釋放,減少繁瑣的異常處理。
- 使用try-with-resources結(jié)構(gòu)無論是否拋出異常在try-block執(zhí)行完畢后都會調(diào)用資源的close方法;
- 使用try-with-resources結(jié)構(gòu)創(chuàng)建多個資源,try-block執(zhí)行完畢后調(diào)用的close方法的順序與創(chuàng)建資源順序相反;
- 使用try-with-resources結(jié)構(gòu),try-block塊拋出異常后先執(zhí)行所有資源(try的()中聲明的)的close方法然后在執(zhí)行catch里面的代碼然后才是finally;
- 只用在try的()中聲明的資源的close方法才會被調(diào)用,并且當(dāng)對象銷毀的時候close不會被再次調(diào)用;
- 使用try-with-resources結(jié)構(gòu)無須顯式調(diào)用資源釋放,編程效率高,代碼更簡潔。