1. 程式人生 > >解決多個io流需要關閉而重複巢狀try-catch-finally的問題

解決多個io流需要關閉而重複巢狀try-catch-finally的問題

問題如圖:

相信大多數人都見過如此狀態,流多了需要層層關閉,需要層層加上try-catch,為保證下一個流能關閉又要加上finally,煩人!!

我們先來一個測試:

public class Test {
    public static void main(String[] args) {
        try {
            System.out.println("第一try");
            throw new Exception("異常");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("finally");
            try {
                throw new Exception("又是異常");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("會執行嗎");
        }
    }
}

執行結果:

提取出重要資訊,finally裡面可以抓到異常後可以繼續往下執行,也就是說finally裡面try-catch抓到異常後也必須把這個程式碼塊執行完。

那麼有人就寫了一個工具類,這種工具類對嗎?


public class IOUtil {
    public static void close(Closeable... closeableList) {
        try {
            for (Closeable closeable : closeableList) {
                if (closeable != null){
                    closeable.close();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

然後

finally{
      IOUtil.close(is, os);
}

看似正確,實則錯誤!!

如果第一個流關閉的時候異常,那麼第二個流close()就不可達,執行不到

這和並列寫沒區別,如下:

finally{

    try{

          is.close();

          os.close();   // 第一個流關閉出異常第二個流關閉就不可達,執行不到,等於沒關

    } catch(Exception e) {

    }

}

那怎麼辦呢?不能寫工具類嗎?

不是不能寫,而是這種寫法是錯誤的,這種情況下應該把try-catch放在for迴圈裡面

,這樣才能保證迴圈會依次關閉流

正確寫法1:

public static void close(Closeable... closeableList) {
    for (Closeable closeable : closeableList) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

然後

finally{
      IOUtil.close(is, os);
}

正確解法2:

public <T extends java.io.Closeable> void close(T t) {
    try {
        if (t != null) {
            t.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

然後

finally {
    close(in);
    close(raf);
    close(br);
}

哪怕其中有流關閉出了異常,也不會影響到其他流的關閉,finally{...}裡面的東西是要執行完的

=============================Talk is cheap, show me the code===========================