關於finally代碼塊的拋出異常問題

之前面試被問道關於異常捕獲的finally代碼塊作用,可能我們想到的會是在finally中進行一些資源關閉的操作。

常見的操作便是IO流這樣的close操作:

public static void throwException(){
        File file = null;
        FileInputStream fis = null;
        try{
            file = new File("abc.txt");
            //可能拋出FileNotFoundException
            fis = new FileInputStream(file);
            fis.read();
        }catch(FileNotFoundException e){
            System.out.println("file not found");
            e.printStackTrace();
        }catch(IOException e){
            e.printStackTrace();
        } finally{
            //這裏存在一個的異常,需要進行處理
            fis.close();
        }
    }

繼續按照IDEA的提示處理,再次catch操作,代碼會變爲這樣:

public static void throwException(){
        File file = null;
        FileInputStream fis = null;
        try{
            file = new File("abc.txt");
            //可能拋出FileNotFoundException
            fis = new FileInputStream(file);
            fis.read();
        }catch(FileNotFoundException e){
            System.out.println("file not found");
            e.printStackTrace();
        }catch(IOException e){
            e.printStackTrace();
        } finally{
            //這裏存在一個的異常,需要進行處理
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

但是在Java核心技術書中,作者建議在finally塊中儘量不要使用會拋出異常的資源回收語句。
也就是這裏的close操作儘量不要出現異常,可是有些資源回收語句確實會拋出異常,此時應該怎麼做呢?

我們可以觀察到close操作拋出的異常是IOException,而前面的文件讀取流也catch了該異常,所以我們可以將兩個異常歸併到一起,然後代碼就變成這樣了:

public static void throwException(){
        File file = null;
        FileInputStream fis = null;
        try{
            try {
                file = new File("abc.txt");
                //可能拋出FileNotFoundException
                fis = new FileInputStream(file);
                fis.read();
            }  finally {
                fis.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

如果你認爲是沒有異常了,那我們執行一下看:
在這裏插入圖片描述
我們可以看到這裏拋出空指針異常,分析代碼我們可以發現fis可能爲空,所以需要在close之前去判斷一下它,防止出現空指針這樣的異常。

public static void throwException(){
        File file = null;
        FileInputStream fis = null;
        try{
            try {
                file = new File("abc.txt");
                //可能拋出FileNotFoundException
                fis = new FileInputStream(file);
                fis.read();
            }  finally {
                if(fis != null){
                    fis.close();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

還有一種做法就是,我們可以將拋出的異常寫到日誌中去,在catch語句塊中寫入。

總結:

1、在捕獲異常的時候我們要清楚自己代碼可能拋出的異常,不要只按照IDE提示的處理策略去處理,那樣可能導致整個代碼很亂,要試着去將異常歸納起來處理;
2、對於可能空的變量操作,我們一定要去做if判斷之後再進行響應的操作;
3、對於異常處理,我們也可以通過日誌寫入的方式做好處理;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章