作為一個有始有終的人,開始做一件事情後,無論事情的結局如何,一定要做收尾工作。程式裡面也是如此,在申請資源的存取權限後,用完之後,就必須釋放。
多數情況下,釋放工作是與程式的運行結果及狀態無關的。一般我們會寫在finally塊中。可是問題又出來了,因為多數情況下close這個函數會拋出異常。而這個異常往往是不影響我們程式的運轉的。
try {
// do something
} catch(Exception ex) {
// do exception
} finally {
try{
in.close();
}catch(Exception ex) {
}
try{
out.close();
}catch(Exception ex) {
}
}
這樣的寫法會影響我們程式的可讀性和美觀。當然,會加大我們程式員的工作量。所以一個萬能的close,是很有必要的。
讓我們來分析下,我們一般性需要調用close函數的有哪些objcet:InputStream,OutputStream,Writer,Reader。(這些東西在jdk1.5後都實現了Closeable介面)。Connection、Statement、ResultSet。所以要實現這樣的函數,只要考慮這些情況就OK了。
我們有兩種思路來實現這個函數,第一種,定義N個不同的參數不同的close函數,利用編譯器的能力實作類別型區分。還有一個辦法,比較簡單只實現一個close(Object o)的函數。我推薦這個,為什麼呢?請看實現
代碼
public static void close(Object o) {
if (o != null) {
try {
if (o instanceof Connection) {
((Connection) o).close();
} else if (o instanceof Statement) {
((Statement) o).close();
} else if (o instanceof ResultSet) {
((ResultSet) o).close();
} else if (o instanceof OutputStream) {
((OutputStream) o).close();
} else if (o instanceof InputStream) {
((InputStream) o).close();
} else if (o instanceof Writer) {
((Writer) o).close();
} else if (o instanceof Reader) {
((Reader) o).close();
} else {
Class c = o.getClass();
c.getMethod("close",new Class[0]).invoke(o,new Object[0]);
}
} catch (Exception ex) {
}
}
}
唯一巧妙的地方就是我們給這個函數加了一個萬能的close功能,只要對象有可訪問的無參數close方法,我們就調用並執行它。
這下我們就可以在前面的例子中我們就可以使我們的代碼初步美化了
try {
// do something
} catch(Exception ex) {
// do exception
} finally {
close(in);
close(out);
}
作為一個追求完美的人(其實是足夠懶),是不會滿足這種程度的簡化的。我們繼續
public static void close(Object... objs) {
for ( int i = 0, size = objs == null ? 0 : objs.length; i < size; i++ ) {
close(objs[i]);
}
}
整個世界清靜了
try {
// do something
} catch(Exception ex) {
// do exception
} finally {
close(in,out);
}