1. 程式人生 > 其它 >Day26---學習Java第二彈

Day26---學習Java第二彈

2021-08-05

Java異常方法

四、自定義異常

在 Java 中你可以自定義異常。如果要自定義異常類,則擴充套件Exception類即可,

因此這樣的自定義異常都屬於檢查異常(checked exception)。如果要自定義非檢查異常,則擴充套件自RuntimeException。

按照國際慣例,自定義的異常應該總是包含如下的建構函式:

一個無參建構函式

一個帶有String引數的建構函式,並傳遞給父類的建構函式。

一個帶有String引數和Throwable引數,並都傳遞給父類建構函式。

一個帶有Throwable 引數的建構函式,並傳遞給父類的建構函式。

下面是IOException類的完整原始碼,可以借鑑。

package java.io;
 
public class IOException extends Exception {
    static final long serialVersionUID = 7818375828146090155L;
 
    public IOException() {
    super();
    }
 
    public IOException(String message) {
    super(message);
    }
 
    public IOException(String message, Throwable cause) {
        super(message, cause);
    }
 
    public IOException(Throwable cause) {
        super(cause);
    }
}

finally塊和return、

首先一個不容易理解的事實:在 try塊中即便有return,break,continue等改變執行流的語句,finally也會執行。

finally中的return 會覆蓋 try 或者catch中的返回值。

finally中的return或異常會抑制(消滅)前面try或者catch塊中的異常。


詳細處理情況介紹:

1.try-catch語句

在Java中,異常通過try-catch語句捕獲。其一般語法形式為:

try {
    // 可能會發生異常的程式程式碼
} catch (Type1 id1){
    // 捕獲並處置try丟擲的異常型別Type1
} catch (Type2 id2){ //捕獲並處置try丟擲的異常型別Type2 }

關鍵詞try後的一對大括號將一塊可能發生異常的程式碼包起來,稱為監控區域。Java方法在執行過程中出現異常,

則建立異常物件。將異常丟擲監控區域之 外,由Java執行時系統試圖尋找匹配的catch子句以捕獲異常

。若有匹配的catch子句,則執行其異常處理程式碼,try-catch語句結束。

匹配的原則是:如果丟擲的異常物件屬於catch子句的異常類,或者屬於該異常類的子類,則認為生成的異常物件與catch塊捕獲的異常型別相匹配。

例1 捕捉throw語句丟擲的“除數為0”異常。

public class TestException {
    public static void main(String[] args) {
        int a = 6;
        int b = 0;
        try { // try監控區域
            
            if (b == 0) throw new ArithmeticException(); // 通過throw語句丟擲異常
            System.out.println("a/b的值是:" + a / b);
        }
        catch (ArithmeticException e) { // catch捕捉異常
            System.out.println("程式出現異常,變數b不能為0。");
        }
        System.out.println("程式正常結束。");
    }
}

執行結果:程式出現異常,變數b不能為0。

程式正常結束。

例1 在try監控區域通過if語句進行判斷,當“除數為0”的錯誤條件成立時引發ArithmeticException異常,

建立 ArithmeticException異常物件,並由throw語句將異常拋給Java執行時系統,由系統尋找匹配的異常處理器

catch並執行相應異 常處理程式碼,列印輸出“程式出現異常,變數b不能為0。”try-catch語句結束,繼續程式流程。

事實上,“除數為0”等ArithmeticException,是RuntimException的子類。而執行時異常將由執行時系統自動丟擲,不需要使用throw語句。

例2 捕捉執行時系統自動丟擲“除數為0”引發的ArithmeticException異常。

    public static void main(String[] args) {
        int a = 6;
        int b = 0;
        try {
            System.out.println("a/b的值是:" + a / b);
        } catch (ArithmeticException e) {
            System.out.println("程式出現異常,變數b不能為0。");
        }
        System.out.println("程式正常結束。");
    }
}

執行結果:程式出現異常,變數b不能為0。

程式正常結束。

例2 中的語句:

System.out.println("a/b的值是:" + a/b);

在執行中出現“除數為0”錯誤,引發ArithmeticException異常。執行時系統建立異常物件並丟擲監控區域,轉而匹配合適的異常處理器catch,並執行相應的異常處理程式碼。

由於檢查執行時異常的代價遠大於捕捉異常所帶來的益處,執行時異常不可查。Java編譯器允許忽略執行時異常,一個方法可以既不捕捉,也不宣告丟擲執行時異常。

例3 不捕捉、也不宣告丟擲執行

public static void main(String[] args) {
        int a, b;
        a = 6;
        b = 0; // 除數b 的值為0
        System.out.println(a / b);
    }

執行結果:

Exception in thread "main" java.lang.ArithmeticException: / by zero
at Test.TestException.main(TestException.java:8)

例4 程式可能存在除數為0異常和陣列下標越界異常。

public class TestException {
    public static void main(String[] args) {
        int[] intArray = new int[3];
        try {
            for (int i = 0; i <= intArray.length; i++) {
                intArray[i] = i;
                System.out.println("intArray[" + i + "] = " + intArray[i]);
                System.out.println("intArray[" + i + "]模 " + (i - 2) + "的值:  "
                        + intArray[i] % (i - 2));
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("intArray陣列下標越界異常。");
        } catch (ArithmeticException e) {
            System.out.println("除數為0異常。");
        }
        System.out.println("程式正常結束。");
    }
}

執行結果:

intArray[0] = 0

intArray[0]模 -2的值: 0

intArray[1] = 1

intArray[1]模 -1的值: 0

intArray[2] = 2

除數為0異常。

程式正常結束。

例4 程式可能會出現除數為0異常,還可能會出現陣列下標越界異常。程式執行過程中ArithmeticException異常型別是先行匹配的,因此執行相匹配的catch語句:

catch (ArithmeticException e){
      System.out.println("除數為0異常。");
 }

需要注意的是,一旦某個catch捕獲到匹配的異常型別,將進入異常處理程式碼。一經處理結束,

就意味著整個try-catch語句結束。其他的catch子句不再有匹配和捕獲異常型別的機會。

Java通過異常類描述異常型別,異常類的層次結構如圖1所示。對於有多個catch子句的異常程式而言,

應該儘量將捕獲底層異常類的catch子 句放在前面,同時儘量將捕獲相對高層的異常類的catch子句放在後面。

否則,捕獲底層異常類的catch子句將可能會被遮蔽。

RuntimeException異常類包括執行時各種常見的異常,ArithmeticException類和ArrayIndexOutOfBoundsException類都是它的子類。

因此,RuntimeException異常類的catch子句應該放在 最後面,否則可能會遮蔽其後的特定異常處理或引起編譯錯誤。