[學習筆記] Java異常處理
程式執行時,可能會發生各種錯誤,一些錯誤是可以避免的,還有些錯誤是隨機出現的且不可避免,一個健壯的程式必須能夠處理這些錯誤;
Java內建一套異常處理機制,使用異常來表示錯誤;
異常是一種類,本身帶有型別資訊,可以在任何地方丟擲,但丟擲以後需要在上層捕獲;
異常
所以的異常類都是Java.lang.Exception類的子類,Exception類是Throwable類的子類;
Throwable類繼承自Object類,它有兩個子類:Error類和Exception類,Error表示嚴重的錯誤,不在程式的處理範疇,而Exception表示異常,需要被捕獲並處理;
Exception分為兩個類:執行時異常(RuntimeException)、非執行時異常(包括IOException);
Java規定必須捕獲的錯誤:Exception類及其子類這樣的檢查性異常,但不包括RuntimeException類及其子類;
Java規定不必捕獲的錯誤:Error類及其子類,RuntimeExcepiton類及其子類;
捕獲異常
使用try/catch關鍵字可用於捕獲異常,try/catch程式碼塊可以放在任何異常可能發生的地方;
try/catch程式碼塊中的程式碼稱為保護程式碼,語法如下:
try { // 程式程式碼 }catch(ExceptionName e) { //Catch 程式碼塊 }
可能發生異常的程式碼要放在try語句塊中,catch語句塊則捕獲異常;
當try語句塊中發生一個異常時,catch語句塊就會被檢查,若發生的異常包含在catch塊中,異常會被傳遞到該catch塊中,就像傳遞引數到方法中一樣;
多個捕獲塊
一個try程式碼塊後面可以跟隨多個catch程式碼塊,每個catch程式碼塊分別捕獲對應的異常及其子類,這樣的情況叫做多重捕獲;
try{ // 程式程式碼 }catch(異常型別1 異常變數名1){ // 程式程式碼 }catch(異常型別2 異常變數名2){ // 程式程式碼 }catch(異常型別3 異常變數名3){ // 程式程式碼 }
try語句塊後可以跟隨任意數量的catch語句塊,但只有一個catch語句塊能被執行;
當try語句塊發生異常時,異常會先拋給第一個catch語句塊,並從上往下逐個匹配,當丟擲異常的型別與某個catch語句塊的異常型別匹配時,異常就會在這個catch塊被捕獲,並不再繼續匹配;
存在多個catch語句塊時,catch語句塊的順序很重要,異常的子類必須放在前面;
finally關鍵字
雖然finally語句塊是寫在catch語句塊後面的程式碼,但finally語句塊中的程式碼在try程式碼塊後面執行;
無論try語句塊中的程式碼是否發生異常,finally程式碼塊中的程式碼總會被執行;
try{ // 程式程式碼 }catch(異常型別1 異常變數名1){ // 程式程式碼 }catch(異常型別2 異常變數名2){ // 程式程式碼 }finally{ // 程式程式碼 }
注意事項
catch語句塊不能獨立於try語句塊存在;
finally語句塊不是強制要求的,是可選的;
try語句塊也不能獨立存在,後面不能既沒有catch語句塊也沒有finally語句塊;
try、catch、finally語句塊之間不能新增任何程式碼;
捕獲多個異常
若某些異常的處理邏輯相同,但異常之間不存在繼承關係,那就需要編寫多個catch語句塊分別來捕獲這些異常;
實際上,一個catch語句塊也可以匹配多個非繼承關係的異常,只需在這些異常之間使用 | 連線;
異常的傳播
若一個方法沒有捕獲到一個檢查性異常,那麼該方法必須將異常丟擲到上層呼叫方法,直到它被某個try/catch語句塊捕獲為止;
throws/throw關鍵字
可以通過將throws關鍵字放在方法簽名的尾部來宣告要丟擲的異常,並在方法內部通過throw關鍵字丟擲異常物件;
throws宣告異常
當一個方法產生一個它不處理的異常時,就需要在方法的頭部宣告此異常以便將異常傳遞到方法外部進行處理;
一個方法可以宣告並丟擲多個異常,多個異常之間通過逗號分隔;
throws方法用於宣告一個方法可能丟擲的所有異常資訊,但不代表異常一定會發生;
throw丟擲異常
與thorws不同,throw用於直接丟擲一個具體的異常,throw關鍵字後面跟隨的就是一個異常類物件;
throw ExceptionObject;
當throw語句執行時,其後的語句將不再執行,此時程式轉到上層呼叫程式執行,直到尋找到對應的catch語句處理異常或最外層的異常處理程式終止程式並列印呼叫棧情況;
try-with-resources
從JDK 7開始,可以使用try-with-resources來開啟資源保證在語句執行完畢後每個資源都被自動關閉;
try (resource declaration) { // 使用資源 } catch (ExceptionType e) { // 異常塊 }
try語句塊宣告和例項化資源,catch語句塊處理關閉資源時可能引發的所有異常;
try-with-resources語句塊中可以宣告多個資源,使用多個資源時使用分號 ; 分隔各個資源;
自定義異常
在程式碼中丟擲異常時,儘量使用JDK定義的異常型別,但我們也可以自己定義新的異常,需要記住的是自定義異常要是Throwable類的子類;
通用異常
Java中的異常還可以分為以下兩種型別:
JVM異常:由JVM丟擲的異常或錯誤,如NullPointerException;
程式級異常:由程式或API程式丟擲的異常,如IllegalArgumentException;
NullPointerException
NullPointerException是最常出現的RuntimeException,NullPointerException即空指標異常;若一個物件為null,呼叫其方法或訪問其欄位就會產生此異常;
指標是屬於C語言的概念,Java當中沒有指標,Java中定義指向物件的變數實際上定義的是物件的引用,Null Pointer其實是Null Reference;