目錄:系統(tǒng)學(xué)習(xí) Java IO---- 目錄,概覽
我們使用流后,需要正確關(guān)閉 Streams 和 Readers / Writers 徽千。
這是通過調(diào)用 close() 方法完成的,看看下面這段代碼:
InputStream input = new FileInputStream("D:\\out.txt");
int data = input.read();
while(data != -1) {
//do something with data...
doSomethingWithData(data);
data = input.read();
}
input.close();
這段代碼乍一看似乎沒問題苫费。
但是如果從 doSomethingWithData() 方法內(nèi)部拋出異常會發(fā)生什么?
對双抽!input.close();
將得不到執(zhí)行的機(jī)會百框,InputStream 永遠(yuǎn)不會關(guān)閉!
為避免這種情況牍汹,可以把關(guān)閉流的代碼放在 finally 塊里面確保一定被執(zhí)行铐维,將代碼重寫為:
InputStream input = null;
try{
input = new FileInputStream("D:\\out.txt");
int data = input.read();
while(data != -1) {
//do something with data...
doSomethingWithData(data);
data = input.read();
}
}catch(IOException e){
//do something with e... log
} finally {
if(input != null) input.close();
}
但是如果 close() 方法本身拋出異常會發(fā)生什么? 這樣流會被關(guān)閉嗎慎菲?
好吧嫁蛇,要捕獲這種情況,你必須在 try-catch 塊中包含對 close() 的調(diào)用露该,如下所示:
} finally {
try{
if(input != null) input.close();
} catch(IOException e){
//do something, or ignore.
}
}
這樣確實可以解決問題睬棚,就是太啰嗦太難看了。
有一種方法可以解決這個問題解幼。就是把這些重復(fù)代碼抽出來定義一個方法抑党,這些解決方案稱為“異常處理模板”。
創(chuàng)建一個異常處理模板书幕,在使用后正確關(guān)閉流新荤。此模板只編寫一次,并在整個代碼中重復(fù)使用台汇,但感覺還是挺麻煩的,就不展開講了。
還好篱瞎,從 Java 7 開始苟呐,我們可以使用名為 try-with-resources 的構(gòu)造,
// 直接在 try 的小括號里面打開流
try(FileInputStream input = new FileInputStream("file.txt")) {
int data = input.read();
while(data != -1){
System.out.print((char) data);
data = input.read();
} }
當(dāng)try塊完成時俐筋,F(xiàn)ileInputStream 將自動關(guān)閉牵素,換句話說,只要線程已經(jīng)執(zhí)行出try代碼塊澄者,inputstream 就會被關(guān)閉笆呆。
因為 FileInputStream 實現(xiàn)了 Java 接口 java.lang.AutoCloseable ,
實現(xiàn)此接口的所有類都可以在 try-with-resources 構(gòu)造中使用粱挡。
public interface AutoCloseable {
void close() throws Exception;
}
FileInputStream 重寫了這個 close() 方法赠幕,查看源碼可以看到其底層是調(diào)用 native 方法進(jìn)行操作的。
try-with-resources構(gòu)造不僅適用于Java的內(nèi)置類询筏。
還可以在自己的類中實現(xiàn) java.lang.AutoCloseable 接口榕堰,
并將它們與 try-with-resources 構(gòu)造一起使用,如:
public class MyAutoClosable implements AutoCloseable {
public void doIt() {
System.out.println("MyAutoClosable doing it!");
}
@Override
public void close() throws Exception {
System.out.println("MyAutoClosable closed!");
} }
private static void myAutoClosable() throws Exception {
try(MyAutoClosable myAutoClosable = new MyAutoClosable()){
myAutoClosable.doIt();
}
}
// 將會輸出:
// MyAutoClosable doing it!
// MyAutoClosable closed!
try-with-resources 是一種非常強(qiáng)大的方法嫌套,可以確保 try-catch 塊中使用的資源正確關(guān)閉逆屡,
無論這些資源是您自己的創(chuàng)建圾旨,還是 Java 的內(nèi)置組件。