使用try-with-resources優雅的關閉IO流

Java類庫中包括許多必須經過調用close方法來手工關閉的資源。例如InputStream、OutputStream和java.sql.Connection。客戶端常常會忽略資源的關閉,形成嚴重的性能後果也就可想而知了。根據經驗,try-finally 語句是確保資源會被適當關閉的最佳方法,就算是發生異常或者返回也同樣:java

public String tryfinally(String path) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(new File(path)));
    try{
        return reader.readLine();
    }finally {
        reader.close();
    }
}

即使用 try-finally 語句正確地關閉了資源,它也存在着些許不足。由於在try塊和finally塊中的代碼,都會拋出異常。例如,底層的物理設備出現異常,那麼調用readLine就會拋出異常,基於一樣的緣由,調用close也會出現異常。在這種狀況下,第二個異常徹底抹除了第一個異常。在異常堆棧軌跡中,徹底沒有關於第一個異常的記錄,這在現實的系統中會致使調試變得很是複雜,由於一般須要看到第一個異常的記錄,這在現實的系統中會致使調試變得很是複雜,由於一般須要看到第一個異常才能診斷出問題何在。雖然能夠經過編寫代碼來禁止第二個異常,保留第一個異常,但事實上沒有人會這麼作,由於實現起來太繁瑣了。sql

如何完美解決這種問題呢?固然是Java7中引入的 try-with-resources 語句。編程

仍是上面的這段代碼,使用 try-with-resources 語句以後,新的代碼以下:性能

public String tryresources(String path) throws IOException {
    try(BufferedReader reader = new BufferedReader(new FileReader(new File(path)))){
        return reader.readLine();
    }
}

使用這種 try-with-resources 不只使代碼變得簡潔易懂,也更容易進行診斷。以上段代碼爲例,若是調用 readLine 和 不可見的 close 方法都拋出異常,後一個異常就會被禁止,以保留第一個異常。事實上,爲了保留你想看到的那個異常,即使多個異常均可以被禁止。這些被禁止的異常並非簡單地被拋棄了,而是會被打印在堆棧軌跡中,並註明它們是被禁止的異常。經過編程調用 getSuppressed 方法還能夠訪問到它們,getSuppressed 方法也已經添加在Java7的Throwable中了。調試

使用 try-with-resources 語句有什麼要求嗎?code

是的,要使用這個構造的資源,必須先實現 AutoCloseable 接口,其中包含了單個返回 void 的 close 方法。Java類庫與第三方類庫中的許多類和接口,如今都實現或擴展了 AutoCloseable 接口。接口

public interface AutoCloseable {
    void close() throws Exception;
}

如下是使用 try-with-resources 的第二個範例:資源

void tryresources(String src,String dst) throws IOException {
     try(InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dst)){
        byte[] bytes = new byte[1024];
        int n;
        while ((n=in.read(bytes))>=0){
            out.write(bytes,0,n);
        }
     }
}

在 try-with-resources 語句中還可使用 catch 子句,就像在平時的 try-finally 語句中同樣。get

public String tryresources(String path){
   try(BufferedReader reader = new BufferedReader(new FileReader(new File(path)))){
        return reader.readLine();
   } catch (IOException e) {
         return null;
   }
}

有了 try-with-resources 語句,在使用必須關閉的資源時,就能更輕鬆地正確編寫代碼了。it

相關文章
相關標籤/搜索