Java異常體系結構以及異常處理機制、自定義異常

什麼是異常

實際工做中,遇到的狀況不多是很是完美的。因此會碰到各類異常。java

軟件程序在運行過程當中,可能遇到各類異常問題(文件格式不對,數據爲空,內存過載...),稱爲異常,英文是:Exception程序員

異常指程序運行中出現的不期而至的各類情況:文件找不到、網絡鏈接失敗、非法參數等編程

異常發生在程序運行期間,它影響了正常的程序執行流程數組

public class Demo01 {
    public static void main(String[] args) {
        new Demo01().a();//StackOverflowError
    }
    public void a(){
        b();
    }
    public void b(){
        a();
    }
}

異常簡單分類

要理解java異常處理是如何工做的,你須要掌握如下三種類型的異常:網絡

  • 檢查性異常:最具表明的檢查性異常是用戶錯誤或者問題引發的異常,這是程序員沒法預見的。例如要打開一個不存在的文件時,一個異常就發生了,這些異常在編譯時不能被簡單地忽略
  • 運行時異常:運行時異常是可能被程序員避免的異常。與檢查性異常相反,運行時異常能夠在編譯時被忽略
  • 錯誤ERROR:錯誤不是異常,而是脫離程序員控制的問題。錯誤在代碼中一般被忽略。例如,當棧溢出時,一個錯誤就發生了,它們在編譯也檢查不到。

異常體系結構

java把異常當作對象來處理,並定義一個基類java.lang.Throwable做爲全部異常的超類ide

在java API中已經定義了許多異常類,這些異常類分爲兩大類,錯誤Error和異常Exceptionthis

Error

Error類對象由Java虛擬機生成並拋出,大多數錯誤與代碼編寫者所執行的操做無關線程

  • Java虛擬機錯誤運行錯誤(Virtual MachineError),當JVM再也不有繼續操做所需的內存資源時,將出現OutOfMemoryError。這些異常發生時,Java虛擬機(JVM)通常會選擇線程終止
  • 還有發生在虛擬機試圖執行應用時,如類定義錯誤(NoClassDefFoundError)、連接錯誤(LinkageError)。這些錯誤是不可查的,由於它們在應用程序的控制和處理能力以外,並且絕大多數是程序運行時不容許出現的情況

Exception

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

  • ArrayIndexOutOfBoundsException(數組下標越界)
  • NullPointerException(空指針異常)
  • ArithmeticException(算術異常)
  • MissingResourceException(丟失資源)
  • ClassNotFoundException(找不到類)等異常,這些異常不是檢查異常,程序中能夠選擇捕獲處理,也能夠不處理

這些異常通常是由程序邏輯錯誤引發的,程序應該從邏輯角度儘量避免這類異常的發生指針

Error和Exception的區別:Error一般是災難性的致命錯誤,是程序沒法控制和處理的,當出現這些異常時,Java虛擬機(JVM)通常會終止線程;Exception一般狀況下是能夠被程序處理的,而且在程序中應該儘量的去處理這些異常

Java異常處理機制

  • 拋出異常
  • 捕獲異常
  • 異常處理五個關鍵字:try、catch、finally、throw、throws

處理異常

處理異常的結構以及在try-catch裏拋出異常:(一個try能夠有多個catch)

package com.exception;

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

        try{//try監控區域
            if(b==0){//主動拋出異常 throw throws
                throw new ArithmeticException();
            }
            System.out.println(a/b);
        }catch(ArithmeticException e){//catch裏的參數是想要捕獲的參數類型
            System.out.println("程序出現異常,變量b不能爲0");
        }finally{//處理善後工做
            System.out.println("finally");
        }

        //finally 能夠不要finally 假設IO、資源、關閉!

        try{//try監控區域
            new Test().a();
        }catch(Throwable e){//catch裏的參數是想要捕獲的參數類型
            System.out.println("棧溢出");
        }finally{//處理善後工做
            System.out.println("finally22222");
        }

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

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

try-catch-finally快捷鍵:ctrl+alt+T

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();//打印錯誤的棧信息 java.lang.ArithmeticException: / by zero
        } finally {
        }
    }
}

在方法中拋出異常

package com.exception;

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

    public void test(int a,int b) throws ArithmeticException{
        if(b==0){// throw throws
            throw new ArithmeticException();//主動拋出異常,通常在方法中使用
        }
    }
}

自定義異常

使用java內置的異常類能夠描述在編程時出現的大部分異常狀況。除此以外,用戶還能夠自定義異常。用戶自定義異常類,只需繼承Exception類便可

在程序中使用自定義異常類,大致可分爲如下幾個步驟:

  1. 建立自定義異常類
  2. 在方法中經過throw關鍵字拋出異常對象
  3. 若是在當前拋出異常的方法中處理異常,可使用try-catch語句捕獲並處理;不然在方法的聲明處經過throws關鍵字指明要拋出給方法調用者的異常,繼續進行下一步操做
  4. 在出現異常方法的調用者捕獲並處理異常

MyException自定義異常類

package com.exception.demo02;
//自定義異常類
public class MyException extends Exception{

    //雙擊+shift可搜索信息
    //傳遞數字>10拋出異常
    private int detatil;

    public MyException(int a) {
        this.detatil = a;
    }
    //toString:異常的打印信息
    @Override
    public String toString() {
        return "MyException{" +
                "detatil=" + detatil +
                '}';
    }
}

Test類

package com.exception.demo02;

public class Test {
    //可能會存在異常的方法

    //兩種寫法
    static void test1(int a){
        System.out.println("傳遞的參數1爲:"+a);
        if(a>10) {
            try {
                throw new MyException(a);//拋出
            } catch (MyException e) {
                e.printStackTrace();//捕獲
            }
        }
        System.out.println("0k");
    }

    static void test2(int a) throws MyException{//捕獲
        System.out.println("傳遞的參數2爲:"+a);

        if(a>10) {
            throw new MyException(a);//拋出
        }

        System.out.println("0k");
    }

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

結果:

總結

  • 處理運行時異常時,採用邏輯去合理規避同時輔助try-catch處理
  • 在多重catch塊後面,能夠加一個catch(Exception)來處理可能會被遺漏的異常
  • 對於不肯定的代碼,也能夠加上try-catch,處理潛在的異常
  • 儘可能去處理異常,切忌只是簡單地調用printStackTrace()去打印輸出
  • 具體如何處理異常,要根據不一樣的業務需求和異常類型去決定
  • 儘可能添加finally語句塊去釋放佔用的資源
相關文章
相關標籤/搜索