Java 常見異常種類

一、什麼是異常數組

結構不佳的代碼不能運行,這是Java的基本理念。性能

發現錯誤的理想時機是在編譯期。然而,編譯器並不能發現全部的錯誤,餘下的問題就須要在程序運行時解決。這就須要錯誤能經過某種方式,把適當的信息 傳遞給特定的接收者處理。Java中的異常處理的目的在於經過使用少許的代碼來簡化大型、可靠的程序的生成,經過此方式讓你的應用中沒有未處理的錯誤,而 且它還帶來了一個明顯的好處:下降錯誤處理代碼的複雜度。學習

異常,根據字面理解,有意外之意。把它置於代碼層面來理解,即阻止了當前方法或做用域繼續執行。spa

在Java中,異常被當作對象來處理,其基類是Throwable。線程

二、Java中的異常類型調試

Java從Throwable直接派生出Exception和Error。其中Exception是能夠拋出的基本類型,在Java類庫、方法以及運行時故障中均可能拋出Exception型異常。Exception表示能夠恢復的異常,是編譯器能夠捕捉到的;Error表示編譯時和系統錯誤,表示系統在運行期間出現了嚴重的錯誤,屬於不可恢復的錯誤,因爲這屬於JVM層次的嚴重錯誤,所以這種錯誤會致使程序終止執行。Exception又分爲檢查異常和運行時異常。code

異常類的結構層次圖以下:orm

clipboard.png

典型的RuntimeException(運行時異常)包括NullPointerException, ClassCastException(類型轉換異常),IndexOutOfBoundsException(越界異常), IllegalArgumentException(非法參數異常),ArrayStoreException(數組存儲異常),AruthmeticException(算術異常),BufferOverflowException(緩衝區溢出異常)等;對象

clipboard.png

非RuntimeException(檢查異常)包括IOException, SQLException,InterruptedException(中斷異常-調用線程睡眠時候),NumberFormatException(數字格式化異常)等。繼承

而按照編譯器檢查方式劃分,異常又能夠分爲檢查型異常(CheckedException)和非檢查型異常 (UncheckedException)。Error和RuntimeException合起來稱爲UncheckedException,之因此這麼 稱呼,是由於編譯器不檢查方法是否處理或者拋出這兩種類型的異常,所以編譯期間出現這種類型的異常也不會報錯,默認由虛擬機提供處理方式。除了Error 和RuntimeException這兩種類型的異常外,其它的異常都稱爲Checked異常。

clipboard.png

三、Java如何處理異常

3.1 try-catch, try-finally, try-catch-finally

對於checked類型異常,咱們要麼對它進行處理,要麼在方法頭使用throws拋出。

public static void createFile() throws IOException{
    File file = new File("C:/test.txt");
    if(!file.exists()){
            file.createNewFile();
    }
}
public static void main(String[] args) {
    try {
        createFile();
    } catch (IOException ex) {
        // handle exception here
    }
}

關於catch須要注意的幾點:

1)、參數的異常類型必須是Throwable類或者其子類。

2)、從上往下的catch語句,其參數類型必須按照從子類到父類順序,由於一旦匹配到一個類型,就會忽略日後的catch。好比IOException必須放到Exception前面,不然編譯器會報錯。

3)、能夠有一個或者多個catch語句,甚至若是有finally語句的狀況下,能夠沒有catch語句,如try-finally。

想要捕獲多個異常,可使用多個catch語句,JDK7之後提供了另一種方式:多重捕獲(multi-catch)。

try{
    // other code
} catch (IOException | SQLException ex) {
    throw ex;  
}

4)、不要忽略異常。空的catch塊會使異常達不到應有的目的,除非諸如關閉FileInputStream的時候,由於你尚未改變文件的狀態,所以沒必要執行任何恢復動做,而且已經從文件中讀取到所須要的信息,所以不用終止正在進行的操做。

關於finally須要注意的幾點:

1)、finally中的代碼老是會被執行,除非在執行try或者catch語句時虛擬機退出(System.exit(1))。

2)、finally塊能夠作一些資源清理工做,如關閉文件、關閉遊標等操做。

3)、finally塊不是必須的。

另外,若是在try和finally塊中都執行了return語句,最終返回的將是finally中的return值。

3.2 異常鏈

經常想要在捕獲一個異常後拋出另一個異常,而且但願把原始異常信息保存下來,這就是異常鏈。在JDK1.4之後,Throwable子類在構造器 中能夠接受一個cause對象做爲參數,表示原始異常,經過這樣把原始異常傳遞給新的異常,使得即便在當前位置建立並拋出了新的異常,也能經過這個異常鏈 追蹤到異常最初發生的位置。

但在Throwable子類中,只有Error, Exception, RuntimeException三類異常類提供了帶cause參數的構造器,其它類型的異常則須要經過initCause()方法。例如定義了CustomException類,能夠這樣使用:

CustomException cmex = new CustomException();
cmex.initCause(new NullPointerException);
throw cmex;

這樣一來,CustomException繼承自Exception或RuntimeException,就屬於自定義異常了。

通常來講,自定義異常的做用有如下情形:

1)、將檢查型異常轉換爲非檢查型異常。

2)、在產生異常時封裝上下文信息、定義異常碼、收集環境對象,有利於信息的傳遞。

四、異常使用指南

1)、在知道該如何處理的狀況下才捕獲異常。

2)、自定義異常類型,用以封裝全部的檢查型異常。

3)、在程序的邊界進行異常捕獲。如服務端相應客戶端的請求,在出口處catch內部有可能產生的異常,並統一throw一個封裝過的異常給客戶端,省得暴露服務端敏感信息。

4)、只針對異常的狀況才使用異常。不要在全部的代碼中習慣性地使用try-catch,由於這會影響性能。

5)、拋出與抽象相對的異常。若是方法拋出的異常與它執行的任務沒有明顯的聯繫,這種情形會令人不知所措。爲了不這個問題,更高層的實現應該捕獲 低層的異常,同時拋出能夠按照高層抽象進行解釋的異常,這種作法被稱爲異常轉譯(exception translation),以下:

try{
    // use lower-level abstraction to do our bidding
} catch(LowerLevelException ex){
    throw new HigherLevelException(...);
}

另一種特殊的異常轉譯稱爲異常鏈,上面已做描述。若是低層的異常對於調試致使高層異常的問題很是有幫助,使用異常鏈就很合適。高層的異常提供訪問方法(Throwable.getCause)來得到低層的異常。

6)、每一個方法拋出的異常要有文檔描述。利用Javadoc的@throws標記,記錄拋出每一個異常的條件。若是一個方法可能拋出多個異常,不要使 用這些異常類的某個超類。如不要聲明一個方法「throws Exception」或「throws Throwable」,這將沒有任何指導信息。

歡迎加入學習交流羣569772982,你們一塊兒學習交流。

相關文章
相關標籤/搜索