天天看點

Java核心技術——異常機制

一、異常分類

Java核心技術——異常機制

說明:1、所有異常都由Throwable繼承而來,下一層分為error和Exception,Error類層次結構描述了Java運作時系統的内部錯誤和資源耗盡錯誤,應用程式不應該抛出這類對象。如果出現了這樣的錯誤,除了通告使用者,并盡力使程式安全的終止之外,再也無能為力,這種情況比較少見。

2、JAVA語言規範将派生于Error類或RuntimeException類的所有異常稱為未檢查異常(unchecked),所有的其他異常稱為已檢查異常(checked),編譯器将核查是否為所有的已檢查異常提供了異常處理器。

3、Exception類是在程式設計時需要重點關注的,它分為兩個分支:RuntimeException和其它異常,由程式錯誤導緻的異常屬于RuntimeException,而程式本身沒問題,但是由于像IO錯誤這類問題導緻的異常屬于其它異常。

派生于RuntimeException的異常包含下面幾種情況,如果出現RuntimException異常就一定是你的問題:

(1)錯誤的類型轉換

(2)數組通路越界:ArrayIndexOutOfBoundsException

(3)通路空指針:NullPointerException

不是派生于RuntimeException的其它異常包括:

(1)試圖在檔案結尾後讀取資料

(2)試圖打開一個不存在的檔案

(3)試圖根據給定的字元串查找Class對象,而這個字元串表示的類并不存在

二、何時抛出異常(throw用于出現異常時抛出異常,throws用于方法首部聲明異常)

(1)調用一個抛出已檢查異常的方法,例如FileInputStream構造器。

(2)程式運作過程中發現錯誤,并且利用throw語句抛出一個已檢查異常。

說明:上述抛出的兩種異常必須聲明或捕獲,告訴調用這個方法的程式員進行捕獲

(3)程式出現錯誤,如a[-1]=0抛出ArrayIndexOutOfBoundsException

(4)Java虛拟機和運作時庫出現的内部錯誤。

說明:這兩種異常不需要聲明/捕獲,因為程式錯誤完全在我們的控制之下,可通過修正程式完成;Java内部錯誤,任何代碼都具有抛出的潛能,我們對它沒有任何控制能力。

總結:一個方法必須聲明所有可能抛出的已檢查異常,而為檢查異常要麼不可控制,要麼就應該避免發生,如果方法沒有聲明所有可能發生的已檢查異常,編譯器就會給出一個錯誤。

注意:如果在子類中覆寫了超類的一個方法,子類方法中聲明的已檢查異常不能比超類方法中聲明的異常更通用!

如果一個方法中聲明将會抛出一個異常,則這個方法就有可能抛出一個這個類的異常或者這個類的某一子類的異常。

三、如何抛出異常

(1)不存在異常:需要自定義異常
派生于Exception的類或者派生于Exception子類的類,通常包含兩個構造器,一個預設,一個帶較長的描述資訊,以便可以調用超類Throwable的toString方法列印詳細資訊,友善調試。

(2)已存在異常:找到一個合适的異常類

(2)建立這個類的一個對象

(3)将對象抛出

四、捕獲異常

語句:

try{

code

more code

more code

}catch(ExceptionType e){

handler for this type

}

可以有多個catch字句捕獲多個異常。

說明:如果在try語句塊中的任何代碼抛出了一個在catch子句中說明的異常類,那麼

(1)程式将跳過try語句塊的其餘代碼

(2)程式将執行catch子句中的處理器代碼

對抛出的異常最好的處理是傳遞給調用者,調用者必須對它進行處理或繼續傳遞。

如果在try語句中的代碼沒有抛出任何異常,那麼程式将跳過catch子句。

五、try catch finally語句執行順序

InputStream in=new FileInputStream(...);

try{

//1

code that might throw exceptions

//2

}catch(IOException e){

//3

show error message

//4

}finally{

//5

in.close();

}

//6

上述代碼執行順序:

(1)代碼沒有抛出異常:1->2->5->6

(2)抛出一個被catch捕獲的異常:

1)catch子句沒有抛出異常:1->3->4->5->6

2)catch字句抛出了一個異常,異常被抛回方法調用者:1->3->5

(3)抛出了一個異常,但未被catch字句捕獲:1->5

總結:finally字句總會被執行,繼續往下執行(語句6)隻有兩種情況:一是沒有抛出異常,另一個是抛出異常被catch字句捕獲并處理,沒有繼續抛出。

六、帶資源的try語句

try(Resource res=...){

word with res

}

若資源實作了Closeabel接口,try塊退出時,自動調用res.close()關閉資源。這是JavaSE7的新功能,建議隻要需要關閉資源,盡量使用帶資源的try語句。還可指定多個資源,用分号分隔:

try(Scanner in=new Scanner();PrintWriter out=new Printer()){

}

六、使用異常機制的技巧

(1)異常處理不能代替簡單的測試,隻在異常情況下使用異常機制:

例如:判斷棧空用if(!empty())條件句時間646ms,而catch(EmptyStackException e)時間21739ms

(2)不要過分的細化異常,一個try多個catch,當任何一個操作出現問題時,整個任務都可以取消

(3)利用異常層次結構:不要隻抛出RuntimeException異常,應該尋找更加适當的子類或建立自己的異常類。不要隻捕獲throwable異常,否則會使代碼更難度,更難維護。

(4)不要壓制異常

(5)不要羞于傳遞異常,傳遞異常要比捕獲異常更好,傳遞給高層方法通知使用者發生了錯誤。