1. 程式人生 > 實用技巧 >Java基礎-異常

Java基礎-異常

1、瞭解Java中的異常體系框架

介紹

異常就是程式執行過程中出現的錯誤。Java中,阻止當前方法或作用域的情況,稱之為異常

Java語言的異常處理框架,是Java語言健壯性的一個重要體現

思想

Java把異常當做物件來處理,並定義一個基類Java.lang.Throwable作為所有異常的超類。在Java API中已經定義了許多異常類,這些異常類分為兩大子類:

1)、錯誤:Error

包括虛擬機器錯誤和執行緒死鎖,一旦Error出現,執行緒就徹底的掛了,被稱為程式終結者

這種情況僅憑程式是無法處理的,在程式中也不會對Error異常進行捕捉和丟擲

2)、異常:Exception

主要指編碼、環境、使用者操作輸入出現問題,Exception主要包括兩大類:

    • RuntimeException:執行時異常,也叫非檢查異常(NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException、ArithmeticException),會由Java虛擬機器自動丟擲並自動捕獲,此類異常的出現絕大數情況是程式碼本身有問題,應該從邏輯上去解決並改進程式碼
    • 檢查異常(其他的一些異常):引起該異常的原因多種多樣,比如說檔案不存在或者是連線錯誤。該異常必須手動在程式碼裡新增捕獲語句來處理該異常。從程式語法角度講是必須警醒處理的異常,如果不處理,程式就不能編譯通過。

2、Java異常的捕獲和處理try、catch、finally關鍵字

思想:Java通過面向物件的思想進行異常處理,把各種不同的異常進行分類,並提供了良好的介面。在Java中每個異常都是一個物件,它是Throwable類或其子類的例項。當一個方法出現異常後邊丟擲一個異常物件,該物件中包含有異常資訊,呼叫這個物件方法可以捕獲到這個異常並可以對其進行處理

關鍵字:Java的異常處理是通過5個關鍵字來實現的:try、catch、finally、throw、throws。

    • try

try語句不可以獨立存在,必須與catch或者finally塊同存,負責捕獲異常,一旦try中發現異常,程式的控制權將被移交給catch塊中異常處理程式

    • catch

負責如何處理。比如發出警告:提示、檢查配置、網路連線、記錄錯誤等,執行完catch塊之後程式跳出catch塊,繼續執行後面的程式碼。

編寫catch塊的注意事項:多個catch塊處理的異常類,要按照先catch子類後catch父類的處理方式,因為會就近處理異常

    • finally

最終執行的程式碼,用於關閉和釋放資源

try{
    //一些會丟擲的異常程式碼
}catch(){
    //處理該異常的程式碼塊
}catch(){
  //處理該異常的程式碼塊
}finally{
 //最終要執行的程式碼  
}

3、Java異常的捕獲和處理之三種異常處理模型

Java的異常梳理模型給予三種操作:

    • 宣告異常

throws-----宣告將要丟擲何種型別的異常。當某個方法可能丟擲某種異常時用於throws宣告可能丟擲的異常,然後交給上層呼叫它的方法程式處理

    • 丟擲異常

throw------將產生的異常丟擲,是丟擲異常的一個動作。一般會用於程式出現某種邏輯時程式會主動丟擲某種特定的型別的異常

    • 捕獲異常

當丟擲一個異常時,可以在try-catch塊中捕獲它並進行處理

1、若執行try塊的過程中沒有異常發生,則跳過catch子句。

2、若是出現異常,try塊中剩餘的語句不在執行

3、開始逐步檢查catch塊,判斷catch塊的異常類例項是否是捕獲的異常型別

4、匹配後執行相應的catch塊中的程式碼

5、如果異常沒有在當前的方法中被捕獲,就會被傳遞給該方法的呼叫者,這個過程一直重複,知道異常被捕獲或傳給main方法(交給jvm來捕獲)

4、Java異常體系中throw和throws的比較

    • throws出現在方法函式頭;而throw出現在函式體。
    • throws表示出現異常的一種可能性,並不一定會發生這些異常;throw則是丟擲了異常,執行throw則一定丟擲了某種異常物件。
    • 兩者都是消極處理異常的方式,只是丟擲或者可能丟擲異常,但是不會由函式去處理異常,真正的處理異常由函式的上層呼叫處理。

5、Java異常體系中catch捕獲異常的順序

    • 一個通用父類可以派生出各種異常類,如果一個catch塊可以捕獲一個父類的異常物件,它就能捕獲哪個父類的所有子類的異常物件
    • 如果捕獲的是多個同類型異常,則子類異常在前,父類異常災後,不然會導致編譯錯誤

這是因為父類異常囊括了子類異常,如果福爾利異常在前,子類異常永遠捕獲不到,導致優勢或無法準確描述錯誤資訊

6、Java異常體系中try-catch-finally的執行流程

執行流程

    • try塊中引起異常,異常程式碼之後的語句不再執行
    • 若被catch塊捕獲,執行匹配的catch塊,然後執行finally語句
    • 若catch塊不能捕獲異常,則執行finally語句,之後將異常傳遞給這個方法的呼叫者
    • finally在try中的return語句執行後,return返回主調函式指點執行

return返回值各種情況

    • try,catch,finally語句塊中均有return,三個語句塊中都沒有丟擲異常:將執行finally語句塊中的return。
    • try,catch,語句塊中均有return,finally語句塊中無return,try中丟擲異常切catch捕捉到異常:將執行catch語句塊的return
    • try,catch,語句塊中均有return,finally語句塊中無return,三個語句塊中竇娥米有丟擲異常:將執行try語句的return
    • try,catch,finally語句塊中均有return,try語句塊中丟擲異常切catch捕捉到異常:將執行finally語句塊的return
    • try,catch,語句塊中均有return,finally語句塊中無return,try語句塊中丟擲異常且catch捕捉到異常,catch語句塊有丟擲異常:將丟擲catch語句塊中的丟擲的異常
    • try,catch,finally語句塊中均有return,try語句塊中丟擲異常且catch捕捉到異常,catch語句塊有丟擲異常:將執行finally語句塊中的return
    • try,catch,語句塊中均有return,finally語句塊中無return,try語句塊中丟擲異常與catch要捕獲的異常型別不一致:將丟擲try語句塊的異常
    • try,catch,finally語句塊中均有return,try語句塊中丟擲異常與catch要捕獲的異常型別不一致:將執行finally語句塊中的return
    • try,catch,finally語句塊中均有return,try和catch語句塊沒有丟擲異常,finally語句塊中丟擲異常:將丟擲finally語句塊中異常

7、Java異常體系中try-finally的使用把場景

流程

    • try塊中引起異常,異常程式碼之後的語句不再執行,直接執行finally語句
    • try塊沒有引發異常,則執行完try塊就執行finally語句

使用場景

    • try-finally可用於不需要捕獲異常的程式碼,可以保證資源在使用後被關閉

如:IO六中執行完相應操作後,關閉相應資源;使用Lock物件保證執行緒同步,通過finally可以保證鎖會被釋放;資料庫連線程式碼時,關閉連線操作等等

8、Java異常體系中finally什麼時候不會被執行

    • 在前面的程式碼中用了system.exit(0)退出程式
    • finally語句中發生了異常
    • 程式所在的執行緒死亡
    • 關閉CPU
    • 在 Java 虛擬機器退出時, Daemon 執行緒中finally不一定會執行

9、Java異常體系值自定義異常

為什麼要使用自定義異常,有什麼好處?

    • 我們在工作的時候,專案是分模組或者分功能開發的,基本不會你一個人開發一整個專案,使用自定義異常類就統一了對外異常展示的方式
    • 有時候我們遇到某些校驗或者問題時,需要直接結束掉當前的請求,這時就可以通過丟擲自定義異常來結束
    • 自定義異常可以在我們專案中某些特殊的業務邏輯時丟擲異常。比如"中性".equals(sex),性別等於中性時我們喲啊丟擲異常,而Java是不會由這種異常的。
    • 使用自定義異常繼承相關的異常來丟擲處理後的異常資訊可以隱藏底層的異常,這樣更安全,異常資訊也更加的直觀。

缺點

    • 毋庸置疑,我們不可能期待JVM自動丟擲一個自定義異常,也不能期待JVM 會自動處理一個自定義異常
    • 發現異常、丟擲異常以及處理異常的工作必須考變成人員在程式碼中利用異常處理機制自己完成。這樣就相應的增加了開發成本和工作量,所以專案沒有必要的話,也不一定非喲啊用上自定義異常,要能夠自己去權衡

使用

    • 所有異常都必須是Throwable的子類
    • 如果希望寫一個檢查性異常類
    • 如果你想寫一個執行時異常類,那麼需要繼承RuntimeExection類