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塊處理。