1. Java使用異常的原因及異常處理機制簡介
(1)使用異常的原因
如果不用異常會產生的缺陷:
1)容易混淆。如果約定返回值為-9時表示異常,那麼當程序最後的計算結果真是-9呢?
2)代碼可讀性差。將異常處理代碼和程序代碼混淆在一起將會降低代碼的可讀性。
3)由調用函數來分析異常,這要求程序對庫函數有很深的瞭解。
而在Java中提供異常處理機制是提供代碼健壯的強有力的方式。使用異常機制它能夠降低錯誤處理代碼的複雜度。
(2)異常處理機制簡介:
Java應用程序中,異常處理機制為:拋出異常,捕獲異常。
拋出異常:
當一個方法出現錯誤引發異常時,方法創建異常對象並交付運行時系統,異常對象中包含了異常類型和異常出現時的程序狀態等異常信息。運行時系統負責尋找處置異常的代碼並執行。
捕獲異常:
在方法拋出異常之後,運行時系統將轉為尋找合適的異常處理器。潛在的異常處理器是異常發生時依次存留在調用棧中的方法的集合。當異常處理器所能處理的異常類型與方法拋出的異常類型相符時,即為合適的異常處理器。運行時系統從發生異常的方法開始,依次回查調用棧中的方法,直至找到含有合適異常處理器的方法並執行。當運行時系統遍歷調用棧而未找到合適 的異常處理器,則運行時系統終止。同時,意味著Java程序的終止。
2. 異常分類:
(1)異常整體分類:
Java異常結構中定義有Throwable類。Exception和Error為其子類:
1)其中Exception表示由於網絡故障、文件損壞、設備錯誤、用戶輸入非法情況導致的異常;
2) 而Error標識Java運行時環境出現的錯誤,例如:JVM內存耗盡。
(2)圖形表示如下:
(3)Exception異常分類:
該異常分類:檢查異常和非檢查異常
1)檢查異常:
編譯驗證,對於聲明拋出異常的任何方法,編譯期強制執行處理或聲明規則,不捕獲這個異常,編譯期就不通過。
2)非檢查異常:
不遵循處理或者聲明規則。在產生此類異常是,不一定非要採取任何適當的操作,編譯器不檢查是否已經解決了這個異常。
檢查異常舉例:
非檢查異常舉例:
3. 異常的常用方法:
4. 異常捕獲:try、catch、finally關鍵字
(1)關鍵字解釋:
1) try{…}語句:
指定了一段代碼,該段代碼就是一次捕獲並處理例外的範圍。
2) catch語句:
(1)在執行過程中,該段代碼可能會產生並拋出一種或幾種類型的異常對象,它後面的catch語句分別對這些異常做相應的處理。如果沒有異常發生catch代碼被略過不執行。
(2)多個try-catch捕獲的異常類型由上至下順序為子類到父類。
3)finally語句:
(1)為異常處理提供一個統一的出口,使得在控制流轉到程序其他部分之前,能夠對程序的狀態做統一的管理。
(2)無論try塊中是否拋出異常,finally塊都會被執行。
(3)可以在finally塊中釋放資源:文件、數據庫連接、網絡連接。
(2)以上三個關鍵字應用語法:
try{
// 程序代碼
}catch(異常類型1 異常的變量名1){
// 程序代碼
}catch(異常類型2 異常的變量名2){
// 程序代碼
}finally{
// 程序代碼
}
(3)try、catch、finally語句塊的執行順序:
1)當try沒有捕獲到異常時:try語句塊中的語句逐一被執行,程序將跳過catch語句塊,執行finally語句塊和其後的語句;
2)當try捕獲到異常,catch語句塊裡沒有處理此異常的情況:當try語句塊裡的某條語句出現異常時,而沒有處理此異常的catch語句塊時,此異常將會拋給JVM處理,finally語句塊裡的語句還是會被執行,但finally語句塊後的語句不會被執行;
3)當try捕獲到異常,catch語句塊裡有處理此異常的情況:在try語句塊中是按照順序來執行的,當執行到某一條語句出現異常時,程序將跳到catch語句塊,並與catch語句塊逐一匹配,找到與之對應的處理程序,其他的catch語句塊將不會被執行,而try語句塊中,出現異常之後的語句也不會被執行,catch語句塊執行完後,執行finally語句塊裡的語句,最後執行finally語句塊後的語句;
(4)代碼實例:
5. 異常拋出:throws/throw關鍵字
如果一個方法沒有捕獲一個檢查性異常,那麼該方法必須使用 throws 關鍵字來聲明。throws 關鍵字放在方法簽名的尾部。
(1)關鍵字具體解釋:
throw
位置是在方法內
程序發生異常而無法處理時,會拋出對應的異常對象,除此之外,在某些時刻,您可能會想要自行拋出異常。
例如:在處理異常結束後,想將異常拋出,讓下一層異常處理塊來捕捉。
throws
位置是在方法簽名處聲明
繼承時需要重寫
繼承的子類可以不處理異常,僅拋出父類聲明的異常;但是不可以拋出額外的異常
(2)throw關鍵字代碼實例:
(3)throws關鍵字代碼實例:
6. 自定義異常
雖然Java類庫已經提供了很多可以直接處理異常的類,但有時候為更加精確的捕獲和處理異常以呈現更好的用戶體驗,需要開發者自定義異常。但是,自定義異常需要繼承Exception。
代碼實例:
7. 異常使用的注意事項:
1)當子類重寫父類的帶有 throws聲明的函數時,其throws聲明的異常必須在父類異常的可控範圍內。
例如,父類方法throws 的是2個異常,子類就不能throws 3個及以上的異常。父類throws IOException,子類就必須throws IOException或者IOException的子類。
2) Java程序可能是多線程的。每一個線程都是一個獨立的執行流,獨立的函數調用棧。那麼,Java中的異常是線程獨立的,線程的問題應該由線程自己來解決,而不要委託到外部,也不會直接影響到其它線程的執行。
3)不要在fianlly中使用return。
4)不要在finally中拋出異常。
5)減輕finally的任務,不要在finally中做一些其它的事情,finally塊僅僅用來釋放資源是最合適的。
6)將盡量將所有的return寫在函數的最後面,而不是try … catch … finally中。