Java的異常處理

1、關鍵字

Java異常處理中有5個關鍵字:

  • try:try{可能發生異常的代碼}
  • catch:catch(異常類型 e){處理異常e的代碼塊}
  • finally:finally{回收資源代碼塊},由於try中代碼可能出現異常,catch代碼不一定會被執行,所以在這兩個代碼塊區中回收資源都是不合理的,finally則是無論try-catch執行情況如何,除非退出虛擬機,fianlly中代碼一定會被執行,所以用於資源回收。
  • throws:f(Object o) throws ExceptionClass1, ExceptionClass2…在方法簽名中,聲明方法可能拋出的異常,意味着可以不使用try-catch捕捉異常,而是將異常交給該方法的調用者處理。throws中有一個原則,子類拋出的異常需要小於或等於父類拋出的異常。
  • throw:用於主動的拋出一個實際異常。

5個關鍵字的關係是:如果方法名後用throws聲明瞭可能的異常,則不需要使用try-catch,由調用者處理異常,如果沒有throws則在try中放可能出現異常的代碼,出現異常後用catch進行捕捉並執行異常處理,然後無論try-catch的情況如何都會執行finally中的語句進行資源回收。而由於實際中異常的類型會有多種情況,所以throw可以主動拋出異常,自定義異常處理代碼。

2、訪問異常信息的方法:

當程序拋出異常類,可以通過類的方法,訪問異常信息:

  • getMessage() :返回異常的描述字符串
  • printStackTrace():將該異常的跟蹤棧信息輸出到標準錯誤輸出
  • getStackTrace():獲得異常跟蹤棧信息。

其中的異常跟蹤棧是:用一個棧來保存發生異常的方法,以後進先出的原則答應出現異常的方法。例如A方法調用了B方法,B方法調用了C方法,C方法拋出了異常,則進棧順序就是ABC,輸出則是以CBA的順序輸出。

3、checked異常和Runtime異常

常見的異常類的繼承關係:
在這裏插入圖片描述
非正常情況分爲兩種:異常(Exception)和錯誤(Error),Error是與虛擬機相關的,如系統崩潰、動態鏈接失敗等,不可捕捉或無法恢復的。

其中異常Exception又分爲兩種,Checked異常和Runtime異常,非RuntimeException的Exception屬於Checked異常,Checked異常認爲是可以修復的異常,需要手動的處理,有兩種處理方式:

  • 1:使用try-catch捕捉異常,並進行處理
  • 2:如果當前方法不知道如何處理,使用throws拋出異常,交給調用者處理

而Runtime異常則不需要手動處理,可以放在普通代碼塊中,交給調用者處理,也可以放在try-catch中進行捕捉。

4、自定義異常類

異常不可能全部都提前定義好,可以根據具體的業務情況自定義異常類。

4.1 儘量定義Runtime異常

自定義異常類一般定義Runtime異常,儘量不定義checked異常,因爲使用checked異常,則必須手動處理,且子類拋出的異常需要小於或等於父類的異常,所以低層級的修改會波及到高層級的簽名,這種設計使得類之間耦合,破壞了封裝。

4.2 定義異常類的方法

而自定義異常類,需要繼承基類RuntimeException(如果是checked則是繼承Exception),然後通常需要提供兩個構造器,一個無參構造器,和一個帶字符串參數的構造器。

class MyException extends RuntimeException{
    // 無參構造器
    public MyException() {
    }

    // 帶一個字符串參數的構造器
    // 傳入的message則是getMessage方法獲得的異常描述字符串
    public MyException(String message) {
        super(message);
    }
}

4.3 異常鏈的處理

異常鏈意思是,有些異常需要逐步處理。例如我們不應該把底層數據庫的異常暴露給用戶,這會帶來兩個問題:1、對於正常用戶,他們看不懂也不希望看到底層的異常。2、對於惡意用戶,暴露底層異常是不安全的。

所以我們需要捕捉異常,同時使用throws-try-catch-throw去捕捉異常,try中捕捉異常,catch處理異常,告訴用戶發生了誤操作,同時保留異常信息,throw拋出,給該方法的調用者通過throws接受,方便底層管理者處理異常信息:

public void test() throws MyException{
        try {
            // 執行可能出現異常的業務代碼
            /*
            代碼塊...
             */
        }
        catch (MyException e){
            // 處理出現的異常,告訴用戶存在誤輸入
            /*
            代碼塊...
             */
         
            // 將異常交給調用者處理底層問題
            throw new MyException("將異常交給調用者處理底層問題");
        }
    }

5、異常處理規則:

  • 1、儘量少用異常
    正常流程控制比異常處理的效率高,所以如果錯誤是可以預期的,儘量不要使用異常,異常的本意是將不可預期的異常處理代碼和正常業務代碼分離。
  • 2、try塊中不要放置大量代碼
    這樣會導致出現異常的可能性加大,並且異常分析的難度也加大,正確的做法是分開多個try塊處理。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章