第八章:異常
第一節:異常
1.1 異常概述
異常:在程式執行過程中,出現的非正常的情況,最終會導緻JVM的非正常停止
在Java等面向對象的程式設計語言中,異常本身就是一個類,産生異常就是建立異常對象并抛出了一個異常對象。Java處理異常的方式是中斷處理。
異常指的并不是文法錯誤,文法錯誤,編譯不通過,不會産生位元組碼檔案,根本不能運作。
1.2 異常體系
異常機制其實是幫助我們找到程式中的問題,異常的根類是
java.lang.Throwable
,其下有兩個子類:
java.lang.Error
與
java.lang.Exception
,平常所說的異常指
java.lang.Exception
Throwable體系:
- **Error:**嚴重錯誤Error,無法通過處理的錯誤,隻能事先避免,好比絕症
- **Execption:**表示異常,異常産生後程式員可以通過代碼的方式糾正,使程式繼續運作,是必須要處理的。好比感冒、闌尾炎
1.3 異常分類
**異常(Execption)的分類:**根據在編譯時期還是運作時期去檢查異常可以分為:
- **編譯時期異常:
。**在編譯(寫代碼)時期就會檢查,如果沒有處理異常,則編譯失敗。(如日期格式化異常 )CheckedExecption
- **運作時期異常:
。**在運作期間,檢查異常。在編譯時期,運作異常編譯器不會檢測(不報錯)。RuntimeExecption
錯誤的一種類型:
-
:記憶體溢出的錯誤。使用的記憶體過大,超出了JVM配置設定的記憶體OutOfMemoryError
1.4 異常的産生過程
當JVM檢測出程式會出現異常時,JVM會做兩件事情:
1、JVM會根據異常傳回的原因建立一個異常對象,這個異常對象包含了異常産生的内容、原因、位置
2、在
getElement
方法中,沒有異常的處理邏輯(try-catch),那麼JVM就會把異常對象抛出給方法的調用者main方法來處理這個異常
main方法接收到了這個異常對象,main方法也沒有異常的處理邏輯,繼續把對象抛出給main方法的調用者JVM處理
JVM接收到了這個異常對象,做了兩件事情:
1、把異常對象(内容、原因、位置)以紅色的字型列印在控制台
2、JVM會終止目前正在執行的java程式---->中斷處理

第二節:異常的處理
java異常處理的五個關鍵字:
try、catch、finally、throw、throws
2.1 抛出異常throw
在java中,提供了一個throw關鍵字,它用來抛出一個指定的異常對象。
操作步驟:
1、建立一個異常對象,封裝一些提示資訊(資訊可以自己編寫)
2、需要将這個異常對象告知給調用者。通過關鍵字throw可以達到将異常傳遞到調用者處的目的。throw對象
throw用在方法内,用來抛出一個異常對象,将這個異常對象傳遞到調用者處,并結束目前方法的執行。
**throw關鍵字作用:**可以使用throw關鍵字在指定的方法中抛出指定的異常
使用格式:
注意:
1、throw關鍵字必須寫在方法的内部
2、throw關鍵字後邊的new的對象必須是Exception或者Exception的子類對象
3、throw關鍵字抛出指定的異常對象,我們就必須處理這個異常對象
- throw關鍵字後邊建立的是RuntimeException或者是RuntimeException的子類對象,我們可以不處理,預設交給JVM處理(列印異常對象,中斷程式)
- throw關鍵字後邊建立的是編譯異常(寫代碼的時候報錯),我們就必須處理這個異常,要麼throws,要麼try…catch
以後工作中,我們首先必須對方法傳遞過來的參數進行合法性校驗,如果參數不合法,那麼我們就必須使用抛出異常的方式,告知方法的調用者傳遞的參數有問題
注意:
NullPointerExecption
和
ArrayIndexOutOfBoundsException
都是運作期異常,我們不用處理,預設交給JVM處理
2.2 Objects非空判斷
Objects類由一些靜态的實用方法組成,這些方法是null-save(空指針安全的)或null-tolerant(容忍空指針的),那麼在它的源碼中,對對象為null的值進行了抛出異常操作
-
:檢視指定引用對象不是nullpublic static <T> requireNonNull(T obj)
public static void method(Object object){
if (object==null)
throw new NullPointerException("傳遞的對象是null");
}
public static void methods(Object obj){
Objects.requireNonNull(obj);
Objects.requireNonNull(obj,"傳遞的對象是null");
}
}
2.3 聲明異常throws
**聲明異常:**将問題辨別出來,報告給調用者。如果方法内通過throw抛出了編譯時的異常,而沒有捕獲處理,那麼必須通過throws進行聲明,讓調用者去處理
關鍵字throws運用于方法聲明之上,用于表示目前方法不處理異常,而是提醒該方法的調用者來處理異常(抛出異常,自己不處理,交給别人處理),最終交給JVM處理---->中斷處理
**聲明異常的格式:**在方法聲明時使用
修飾符 傳回值類型 方法名(參數清單) throws 異常類名1,異常類名2...{
throw new AAAException("産生原因");
throw new BBBException("産生原因");
...
}
注意:
1、throws關鍵字必須寫在方法聲明上
2、throws關鍵字後邊聲明的異常必須是Exception或者是Exception的子類
3、方法内部如果抛出了多個異常對象,那麼throws後邊必須也聲明多個異常。如果抛出的多個異常對象有子父類關系,那麼直接聲明父類異常即可
4、調用了一個聲明抛出異常的方法,我們就必須處理聲明的異常,要麼繼續使用throws聲明抛出,交給方法的調用者處理,最終交給JVM,要麼try…catch自己處理異常
2.4 try…catch處理異常
**try…catch:**異常處理的第二種方式,自己處理異常
格式:
try{
可能産生異常的代碼
}catch(定義一個異常的變量,用來接收try中抛出的異常對象){
異常的處理邏輯,産生異常的對象之後,怎麼處理異常對象
一般在工作中,會把異常的資訊記錄到一個日志中
}
...
catch(異常類型 變量名){
}
注意:
1、try中可能會抛出多個異常對象,那麼就可以使用多個catch來處理這些異常對象
2、如果try中産生了異常,那麼就會執行catch中的異常處理邏輯,執行完畢catch中的處理邏輯,繼續執行try…catch之後的代碼。如果try中沒有産生異常,那麼就不會執行catch中異常的處理邏輯,執行完try…catch之後的代碼
2.5 Throwable類中3個處理異常的方法
Throwable類中定義了一些檢視方法:
-
:擷取異常的描述資訊,原因。提示給使用者看的時候,就提示的錯誤原因。簡短描述public String getMessage()
-
:擷取異常的類型和異常描述資訊(不用)。**預設調用toString方法。**詳細資訊public String toString()
-
:列印異常的跟蹤棧資訊并輸出到控制台。列印的資訊最為全面public void printStackTrace()
2.6 finally代碼塊
**finally:**有一些特定的代碼無論異常是否發生,都需要執行。另外,因為異常會引發程式跳轉,導緻有些語句執行不到。而finally就是解決這個問題的,在finally代碼塊中存放的代碼都是一定會被執行的。
什麼時候的代碼必須最終執行?
當我們在try語句塊中打開了一些實體資源(磁盤檔案/網絡連接配接/資料庫連接配接等),我們都得在使用完成之後,最終關閉打開的資源
文法:
try{
可能産生異常的代碼
}catch(定義一個異常的變量,用來接收try中抛出的異常對象){
異常的處理邏輯,産生異常的對象之後,怎麼處理異常對象
一般在工作中,會把異常的資訊記錄到一個日志中
}
...
catch(異常類型 變量名){
}finally{
無論是否出現異常都會執行
}
注意:
1、finally不能單獨使用,必須和try一起使用
2、finally一般用于資源釋放(資源回收),無論程式是否出現異常,最後都要資源釋放
2.7 異常的注意事項
- 多個異常使用捕獲如何處理
- 1、多個異常分别處理
- 2、多個異常一次捕獲,多次處理
- 3、多個異常一次捕獲一次處理
try{ 異常1; 異常2; ... 異常n; }catch(){ }catch(){ }... catch(){ }
一個try,多個catch注意事項:catch裡定義的異常變量,如果有父子關系,那麼子類的異常變量必須寫在上面,否則就會報錯
- 運作時異常被抛出可以不處理,既不捕獲,也不聲明抛出,預設會給虛拟機處理,終止程式,什麼時候不抛出運作異常再來繼續執行程式
- 如果finally有return語句,永遠傳回finally中的結果,應該避免該情況
- 如果父類抛出了多個異常,子類覆寫父類的方法時,隻能抛出相同的異常或者是它的子類
- 父類方法沒有抛出異常,子類覆寫父類該方法時也不可能抛出異常。此時子類産生該異常,隻能捕獲處理,不能聲明抛出
- 在try/catch後可以追加finally代碼塊,其中的代碼一定會被執行,通常用于資源回收
第三節:自定義異常
什麼是自定義異常類:
在開發中根據自己業務的異常情況來定義異常類
異常類怎麼定義:
1、自定義一個編譯期異常:自定義類 并繼承于
java.lang.Exception
2、自定義一個運作時期的異常類:自定義類 并繼承于
java,langRuntimeException
格式:
public class XxxException extends Exception/RuntimeException{
添加一個空參數的構造方法
添加一個帶異常資訊的構造方法
}
注意:
1、自定義異常類一般都是以Exception結尾,說明該類是一個異常類
2、自定義異常類,必須繼承Exception或者RuntimeException
- 繼承Exception:那麼自定義的異常類就是一個編譯期異常,如果方法内部抛出了編譯期異常,就必須處理這個異常,要麼throws,要麼try…catch
- 繼承RuntimeException:那麼自定義的異常類就是一個運作期異常,無需處理,交給虛拟機處理(中斷處理)
public class RegisterException extends Exception{
public RegisterException() {
}
public RegisterException(String s){
super(s);
}
}