1. 程式人生 > >java異常處理 | 菜鳥教程

java異常處理 | 菜鳥教程

異常的體系 Throwable

Error
通常指JVM出現重大問題如:執行的類不存在或者記憶體溢位等。
不需要編寫針對程式碼對其處理,程式無法處理。
Exception
在執行時執行出現的一些情況,可以通過try,catch,finally處理

1.異常處理兩種方式:

1、捕獲異常:try catch 直接處理可能出現的異常! 
2、宣告異常:throws 宣告告訴呼叫者可能的異常,暴露問題,呼叫者自己處理!

我的總結:
Exception 和 Error的子類名大都是以父類名作為字尾。
Java異常其實是對不正常情況的一種描述,並將其封裝成物件;
Java在 設計異常體系時,將容易出現的異常情況都封裝成了物件。

2、異常處理格式

異常處理的5個關鍵字
try ,catch,
finally
throw, throws

我的總結:
捕獲異常:先捕獲小異常再捕獲大異常。
程式是調出來的,不是寫出來的;多測試是程式設計師的必修課。
異常處理後,程式不會因為出現異常而退出!

異常處理格式

try{
        //可能出異常的程式碼
} catch(異常類  物件){
        //處理該異常型別的語句
}
[finally] {
        //一定會執行的程式碼
        //catch塊使用System.exit(1);除外
}

備註:當try語句塊出現異常,程式會自動跳到catch語句塊去找匹配的異常型別,並執行異常處理語句,finally語句塊是異常的統一出口。

3、多異常處理

宣告異常時儘可能宣告具體異常型別,方便更好的處理;
方法宣告幾個異常就對應有幾個catch塊;
若多個catch塊中的異常出現繼承關係,父類異常catch塊放在最後;
在catch語句塊使用Exception類作為異常型別時:
所有子類例項都可以使用父類接收(向上轉型),即所有的異常物件都可以使用Exception接收;
注:在java處理多異常時捕獲小範圍的異常必須放在大範圍異常之前。

java7 - 同時捕獲多個異常型別
Java7之前:

try {
    int a = Integer.parseInt("1");
    int b = Integer.parseInt("0");
    int c = a / b;
    System.out.println(c);
} catch (NumberFormatException e)
{
   e.printStackTrace();
} catch(ArithmeticException e) 
{
    e.printStackTrace();
}

Java7:將多個異常寫到了同一個catch程式碼塊

try {
Integer a = Integer.parseInt("1");
Integer b = Integer.parseInt("0");

Integer c = a / b;

System.out.println(c);

} catch (NumberFormatException 
    | ArithmeticException  e ) {
     e.printStackTrace();
}

4、異常的分類

異常分類:
編譯時被檢查異常; —> Checked異常
在程式中必須使用try…catch處理;
編譯時不被檢測的異常; —> Runtime異常
可以不使用try…catch處理,但一旦出現異常就將由JVM處理。

異常的分類之Runtime異常

RuntimeException(執行時異常)是指因設計或實現方式不當而導致的問題.
說白了,就是程式設計師造成的,程式設計師小心謹慎是完全可以避免的異常.比如,事先判斷物件是否為null就可以避免NullPointerException異常,事先檢查除數不為0就可以避免ArithmeticException異常;

特點:
這種異常Java編譯器不會檢查它,也就說程式中出現這類異常的時候,即使不處理也沒有問題,但是一旦出現異常,程式將異常終止,若採用異常處理,則會被相應的程式執行處理.

異常的分類之Checked異常

除了RuntimeException以及子類,其他的Exception及其子類都是受檢查異常,我們也可以稱為非RuntimeException異常.
特點:
Java編譯器會檢查它,也就說程式中一旦出現這類異常,要麼是沒有try-catch語句捕獲,或throws語句沒有宣告丟擲它,編譯就不會通過,也就說這種異常,程式要求必須處理.

5、宣告異常(throws)

在可能出現異常的方法上宣告丟擲可能出現異常的型別:
宣告的時候儘可能宣告具體的異常,方便更好的處理.
當前方法不知道如何處理這種異常,可將該異常交給上一級呼叫者來處理(非RuntimeException型別的異常)。
方法一旦使用throws宣告丟擲方法內可能出現的異常型別, 該方法就可以不再過問該異常了;
一個方法呼叫另一個使用throws宣告丟擲的方法,自己要麼try…catch , 要麼也throws;

格式: 
public 返回值型別 方法名(引數列表…) 
throws 異常類A,異常類B… {

}

6、throw

自行丟擲一個異常物件,丟擲異常類的物件;
若throw丟擲的是Runtime異常:
程式可以顯示使用try…catch來捕獲並處理,也可以不管,直接交給方法呼叫者處理;
若throw丟擲Checked異常:
要麼放在try裡自己處理,要麼放在一個throws宣告的方法裡面,交給呼叫者處理。

  public static void main(String[] args) {
        try {
              fn1(1);
        } catch (Exception e) { e.printStackTrace(); }
        fn2(2);
    }
    public static void fn1(int a) throws Exception{
        if(a >0) { throw new Exception("fn1 -- a值不合法"); }
    }
    public static void fn2(int a) {
        if(a >0) { throw new RuntimeException("a值不合法"); }
    }

throws & throw

throws用於在方法上宣告該方法不需要處理的異常型別。
throw用於丟擲具體異常類的物件。
throws與throw的區別:
thorws用在方法上,後面跟異常類名,可以是多個異常類。
throw用在方法內,後面跟異常物件,只能是一個。

7、finally

異常的統一出口:
不管try塊程式是否異常,也不管哪個catch執行,finally塊總會執行。
try語句塊或會執行的catch語句塊使用了JVM系統退出語句例外;//System.exit(1);
try塊必須和 catch塊或和finally同在,不能單獨存在,二者必須出現一個。
不要在finally中使用return 或throw語句,否則將會導致try、catch中的return或throw失效。

我的總結:finally程式碼塊只在一種情況下不執行:System.exit(0);

package reviewDemo;

public class Demo19 {
    public static void main(String[] args) {
        try{
            System.out.println(17/0);
        }catch(Exception e){
            //e.printStackTrace();
            System.out.println("程式錯誤,請修正!");
        }finally{
            System.out.println("這是finally程式碼塊!");
        }
    }

}
輸出:
程式錯誤,請修正!
這是finally程式碼塊!

8、throw和catch同時使用

當異常出現在當前方法中,程式只對異常進行部分處理,還有一些處理需要在方法的呼叫者中才能處理完成,此時還應該再次丟擲異常,這樣就可以讓方法的呼叫者也能捕獲到異常;

public static void buy(String price) throws Exception {
    try {
        if(price != null)
            Double.parseDouble(price);
    } catch (Exception e) {
        e.printStackTrace();
        throw new Exception("價格不能只能是數字組成");
    }
}
public static void main(String[] args)  {
    try {
        buy(null);
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
}