閱讀262 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Java IO: 異常處理

流與Reader和Writer在結束使用的時候,需要正確地關閉它們。通過調用close()方法可以達到這一點。不過這需要一些思考。請看下邊的代碼:

InputStream input = new FileInputStream("c:\\data\\input-text.txt");

int data = input.read();

while(data != -1) {

    //do something with data...  

    doSomethingWithData(data);

    data = input.read();

}

input.close();

第一眼看這段代碼時,可能覺得沒什麼問題。可是如果在調用doSomethingWithData()方法時出現了異常,會發生什麼呢?沒錯,這個InputStream對象就不會被關閉。

為了避免異常造成流無法被關閉,我們可以把代碼重寫成這樣:

InputStream input = null;

try{

    input = new FileInputStream("c:\\data\\input-text.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, perhaps rethrow etc.

} finally {

    if(input != null)

        input.close();

}

注意到這裏把InputStream的關閉代碼放到了finally塊中,無論在try-catch塊中發生了什麼,finally內的代碼始終會被執行,所以這個InputStream總是會被關閉。

但是如果close()方法拋出了異常,告訴你流已經被關閉過了呢?為了解決這個難題,你也需要把close()方法寫在try-catch內部,就像這樣:

} finally {

    try{

        if(input != null)

            input.close();

    } catch(IOException e){

        //do something, or ignore.

    }
}

這段解決了InputStream(或者OutputStream)流關閉的問題的代碼,確實是有一些不優雅,盡管能夠正確處理異常。如果你的代碼中重複地遍布了這段醜陋的異常處理代碼,這不是很好的一個解決方案。如果一個匆忙的家夥貪圖方便忽略了異常處理呢?

此外,想象一下某個異常最先從doSomethingWithData方法內拋出。第一個catch會捕獲到異常,然後在finally裏程序會嚐試關閉InputStream。但是如果還有異常從close()方法內拋出呢?這兩個異常中得哪個異常應當往調用棧上傳播呢?

幸運的是,有一個辦法能夠解決這個問題。這個解決方案稱作“異常處理模板”。創建一個正確關閉流的模板,能夠在代碼中做到一次編寫,重複使用,既優雅又簡單。詳情參見Java異常處理模板

Java7中IO的異常處理

從Java7開始,一種新的被稱作“try-with-resource”的異常處理機製被引入進來。這種機製旨在解決針對InputStream和OutputStream這類在使用完畢之後需要關閉的資源的異常處理。可以瀏覽Try with Resource in Java 7獲得更多信息。

最後更新:2017-05-23 13:31:59

  上一篇:go  linux 批量建立信任關係
  下一篇:go  百度NLP | 智能寫作機器人:不搶人類飯碗,我們隻想人機協作