Java異常處理詳解

1JAVA異常

異常指不期而至的各種狀況,如:文件找不到、網絡連接失敗、內存越界等。異常是一個事件,它發生在程序運行期間,干擾了正常的指令流程。Java通過API中Throwable類的衆多子類描述各種不同的異常。因而,Java異常都是對象,是Throwable子類的實例,描述了出現在一段編碼中的錯誤條件。當條件生成時,錯誤將引發異常。

Java異常類層次結構圖:

這裏需要針對兩個重要的子類說明,Exception(異常)和 Error(錯誤)。

Error(錯誤):是程序無法處理的錯誤,表示運行應用程序中較嚴重問題。

大多數錯誤與代碼編寫者執行的操作無關,而表示代碼運行時 JVM(Java 虛擬機)出現的問題。例如,OutOfMemoryError、NoClassDefFoundError、StackOverFlowError。這些異常發生時,Java虛擬機(JVM)一般會選擇線程終止。

Exception(異常):是程序本身可以處理的異常。

如上圖,它又分爲IO異常和運行時異常。我們平時最常見的就是運行時異常。比如NullPointerException、ArrayIndexOutOfBoundException等。 

同時Java的異常(包括Exception和Error)又分爲可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)

可查異常:簡單理解爲,Java編譯器或者IDE會檢查它,會有提示錯誤信息。除 了RuntimeException及其子類以外,其他的Exception類及其子類都屬於可查異常,如IOException,SQLException。當程序中可能出現這類異常,要麼用try-catch語句捕獲它,要麼用throws子句聲明拋出它,否則編譯不會通過。

不可查異常:反之,編譯器不要求強制處置的異常就是不可查異常。包括RuntimeException與其子類和錯誤(Error),如NullPointerException等常見異常。這些異常一般是由程序邏輯錯誤引起的,程序應該從邏輯角度儘可能避免這類異常的發生。我們現在接觸最多的也是現在要講的就是這類異常處理。

2、異常處理機制

在 Java 應用程序中,異常處理機制爲:拋出異常,捕捉異常。 

拋出異常使用throws子句或者throw new Exception()。

捕捉異常通過try-catch語句或者try-catch-finally語句實現。

總體來說,Java規定:對於可查異常必須捕捉、或者聲明拋出。允許忽略不可查的RuntimeException和Error。但是,我們提倡所有的運行時異常都要進行捕捉處理,或者拋給方法的調用者。否則出現問題,只會給用戶展現一些不友好的錯誤代碼。或者不拋出也不捕捉處理,導致方法的調用者沒有任何消息,一頭霧水。 

下面我們以實際開發來說明兩種處理機制的配合使用,達到系統的友好性和穩定性。

3.1 異常捕捉

Java中用try-catch塊來捕捉可能發生的異常。以代碼來說明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void core() throws Exception {
        try {
            String a = "";
            Integer.valueOf(a);//製造一個java.lang.NumberFormatException異常
            System.out.println("1、***");
        catch (Exception ex) {
            System.out.println("2、***");
            ex.printStackTrace();
            throw ex;//第二種情況
        finally {
            System.out.println("3、***");
        }
        System.out.println("4、***");
    }

 

這裏分兩種情況,一種是在catch子句中捕捉處理異常,但不向上throw異常;一種就是捕捉處理並且向上拋出異常。

1
2
3
4
//第一種輸出結果:
2、***
3、***
4、***
1
2
3
//第二種輸出結果:
2、***
3、***

解說:第二種情況向上拋出異常後,當前線程就會中斷,try-catch塊後面的代碼就不會執行,這裏平時可能需要注意。當選擇向上拋出異常的時候,調用者要麼用try-catch捕捉處理,要麼繼續向上拋出。 

建議:方法是向上拋出異常還是捕捉異常進行處理,這需要根據當前方法所處的代碼層級。以Java開發中典型的三層架構來講。第一層爲API層或者叫接口層,供外部調用,第二層爲server層或者叫業務層,這裏仍不是真正的代碼處理,也只是做一些參數的封裝之類的;第三層就是core層,核心層,這層主要是寫代碼來實現功能,比如查詢數據庫,調用第三方接口等。

經驗:從系統架構的鬆耦合和實現上來講,API層和Server層不做異常的處理工作,全部的異常處理交給core層來處理之後,返回定義好的錯誤代碼和錯誤信息給上層,最後由API層將錯誤信息返回到顯示層展示。同時在core層代碼中的catch子句中打印輸出的堆棧錯誤信息,供開發者分析錯誤原因。 

那麼什麼時候需要方法拋出異常呢?

比如在core層中,有一個業務方法比較複雜,那麼就需要將代碼重構,抽出多個子方法來單獨處理,只在主方法中一次調用抽出的子方法。那麼此時,子方法中就需要進行異常拋出了,否則主方法在執行到其中的一個方法時,調用子方法遇到異常時就不知道發生什麼了,線程仍然會繼續調用接下來的方法,那此時系統就比較脆弱了,而且會出現各種問題。

 

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