1. 程式人生 > 其它 >Java筆記_異常機制

Java筆記_異常機制

異常機制(Exception)

一、什麼是異常

  • 實際工作中,遇到的情況不可能是非常完美的。比如:你寫的某個模組,使用者輸入不一定符合你的要求、你的程式要開啟某個檔案,這個檔案可能不存在或者檔案格式不對,你要讀取資料庫的資料,資料可能是空的等。我們的程式再跑著,記憶體或硬碟可能滿了。等等。
  • 軟體程式在執行過程中,非常可能遇到剛剛提到的這些異常問題,我們叫異常,英文是:Exception,意思是例外。這些,例外情況,或者叫異常,怎麼讓我們寫的程式做出合理的處理。而不至於程式崩潰。
  • 異常指程式執行中出現的不期而至的各種狀況,如:檔案找不到、網路連線失敗、非法引數等。
  • 異常發生在程式執行期間,它影響了正常的程式執行流程。

舉例異常

Exception in thread "main" java . lang . StackoverflowError(比較嚴重的異常)

package com.exception;

public class Demo01 {

    public static void main(String[] args) {

        //用匿名內部類呼叫就不用寫很長了
        new Demo01().a();

    }

    public void a() {
        b();
    }
    public void b() {
        a();
    }
}

Exception in thread "main" java.lang.ArithmeticException: / by zero(被除數不能為0的異常,算術異常)

package com.exception;

public class Demo01 {
    public static void main(String[] args) {
        System.out.println(11/0);
    }
}

簡單分類

  • 要理解Java異常處理是如何工作的,你需要掌握以下三種類型的異常:

  • 檢查性異常:最具代表的檢查性異常是使用者錯誤或問題引起的異常,這是程式設計師無法預見的。例如要開啟一個不存在檔案時,一個異常就發生了,這些異常在編譯時不能被簡單地忽略。

  • 執行時異常:執行時異常是可能被程式設計師避免的異常。與檢查性異常相反,執行時異常可以在編譯時被忽略。

  • 錯誤ERROR(致命性的):錯誤不是異常,而是脫離程式設計師控制的問題。錯誤在程式碼中通常被忽略。例如,當棧溢位時,一個錯誤就發生了,它們在編譯也檢查不到的。

二、異常體系結構

  • Java把異常當作物件來處理,並定義一個基類java.lang.Throwable作為所有異常的超類。
  • 在Java API中已經定義了許多異常類,這些異常類分為兩大類,錯誤Error和異常Exception.

Error

  • Error類物件由Java虛擬機器生成並丟擲,大多數錯誤與程式碼編寫者所執行的操作無關。

  • Java虛擬機器執行錯誤(Virtual MachineError),當JVM不再有繼續執行操作所需的記憶體資源時,將出現OutOfMemoryError。這些異常發生時,Java虛擬機器(JVM)一般會選擇執行緒終止;

  • 還有發生在虛擬機器試圖執行應用時,如類定義錯誤(NoClassDefFoundError) 、連結錯誤(LinkageError)。這些錯誤是不可查的,因為它們在應用程式的控制和處理能力之外,而且絕大多數是程式執行時不允許出現的狀況。

Exception

  • 在Exception分支中有一個重要的子類RuntimeException (執行時異常)

    • ArrayIndexOutOfBoundsException (陣列下標越界)
    • NullPointerException (空指標異常)
    • ArithmeticException (算術異常)
    • MissingResourceException (丟失資源)
    • ClassNotFoundException (找不到類)等異常,這些異常是不檢查異常,程式中可以選擇捕獲處理,也可以不處理。
  • 這些異常一般是由程式邏輯錯誤引起的, 程式應該從邏輯角度儘可能避免這類異常的發生;

  • Error和Exception的區別: Error通常是災難性的致命的錯誤,是程式無法控制和處理的,當出現這些異常時,Java虛擬機器(JVM)一般會選擇終止執行緒; Exception通常情況下是可以被程式處理的,並且在程式中應該儘可能的去處理這些異常。

三、Java異常處理機制

  • 丟擲異常
  • 捕獲異常
  • 異常處理五個關鍵字
    • try、catch、 finally、 throw、throws

四、處理異常

捕獲ArithmeticException異常

package com.exception;

public class Test {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        try {//監控區域
            System.out.println(a/b);
        }catch (ArithmeticException e){//catch 捕獲異常
            System.out.println("程式出現異常,變數b不能為0");
        }finally {//處理善後工作
            System.out.println("finally");
        }
        //finally   可以不要finally,但是try-catch必須一起使用

    }
}

捕獲多個異常

package com.exception;

public class Test {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        //假設要捕獲多個異常:從小到大!
        try { //try監控區域
            System.out.println(a/b);
        } catch (Error e){ //catch( 想要捕獲的異常型別! )捕獲異常
            System.out.println("Error");
        } catch (Exception e){
            System.out.println("Exception");
        } catch (Throwable t){
            System.out.println("Throwable");
        } finally { //處理善後工作
            System.out.println("finally");
        }

            //finally   可以不要finally,但是try-catch必須一起使用

    }
}

printStackTrace(),列印錯誤的棧資訊

package com.exception;

public class Test2 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        //選中需要包裹的程式碼塊,Ctrl+Alt+T
        try {
            System.out.println(a/b);
        } catch (Exception e) {
            //System.exit(1);//手動結束程式
            e.printStackTrace();//列印錯誤的棧資訊
        } finally {
        }
    }
}

在方法中、方法上捕獲異常

package com.exception;

public class Test {
    public static void main(String[] args) {
        try {
            new Test3().test(1,0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //假設這方法中,處理不了這個異常。方法上丟擲異常
    public void test(int a,int b) throws ArithmeticException{
        if (b==0){//throw  throws
        	//方法中捕獲
            throw new ArithmeticException(); //主動的丟擲異常,一般在方法中使用
        }
        System.out.println(a/b);
    }
}

五、自定義異常

  • 使用Java內建的異常類可以描述在程式設計時出現的大部分異常情況。除此之外,使用者還可以自定義異常。使用者自定義異常類,只需繼承Exception類即可。

  • 在程式中使用自定義異常類,大體可分為以下幾個步驟:

    1. 建立自定義異常類。
    2. 在方法中通過throw關鍵字丟擲異常物件。
    3. 如果在當前丟擲異常的方法中處理異常,可以使用try-catch語句捕獲並處理; 否則在方法的宣告處通過throws關鍵字指明要丟擲給方法呼叫者的異常,繼續進行下一步操作。
    4. 在出現異常方法的呼叫者中捕獲並處理異常。

MyException

package com.exception.demo02;

//自定義的異常類
public class MyException extends Exception{

    //傳遞數字>10;
    private int detail;

    public MyException(int a) {
        this.detail = a;
    }

    //toString:異常的列印資訊


    @Override
    public String toString() {
        return "MyException{" +
                "detail=" + detail +
                '}';
    }

}

測試

package com.exception.demo02;

public class Test {

    //可能會存在異常的方法.
    static  void test(int a) throws MyException {
        System.out.println("傳遞的引數為"+a);

        if (a>10){
            throw new MyException(a);//這裡選擇了丟擲異常
        }
        System.out.println("ok");
    }

    public static void main(String[] args) {
//        try {
//            test(6);
//        } catch (MyException e) {
//            System.out.println("MyException==>"+e);
//        }


        try {
            Test.test(6);
        } catch (MyException e) {
            System.out.println("MyException==>"+e);
        }

//        Test test = new Test();
//        try {
//            test.test(6);
//        } catch (MyException e) {
//            System.out.println("MyException==>"+e);
//        }

        /*
        輸出結果
        傳遞的引數為6
        ok
        */
        /*
        輸出結果(捕獲自定義的異常)
        傳遞的引數為11
		MyException==>MyException{detail=11}
        */
    }
}

六、總結

實際應用中的經驗總結

  • 處理執行時異常時,採用邏輯去合理規避同時輔助try-catch處理
  • 在多重catch塊後面,可以加一個catch (Exception) 來處理可能會被遺漏的異常
  • 對於不確定的程式碼,也可以加上try-catch,處理潛在的異常
  • 儘量去處理異常,切忌只是簡單地呼叫printStackTrace()去列印輸出
  • 具體如何處理異常,要根據不同的業務需求和異常型別去決定
  • 儘量新增finally語句塊去釋放佔用的資源