一切皆對象,異常也同樣

   認識異常

  異常基礎

  所謂的異常,就是程序按照正常執行邏輯走着走着遇到問題,崴了腳或閃了腰,已經沒法再繼續走下去了。怎麼辦呢?就像有病要治病同樣,有異常就得處理異常。Java提供了基本的語法來處理異常:一中是throw(s)語法,叫拋異常;一種是try-catch-finally語法,叫作捕獲異常。Java是面向對象的,在Java的世界裏一切皆是對象,因此異常天然也被當作是一種對象,當異常發生,就是建立了一個異常對象,咱們使用兩種語法來處理異常對象就好了,語法也很簡單,下面只簡單示例:程序員

public class Test {

    //繼續外拋異常
    public void test1() throws FileNotFoundException {
        new FileInputStream("D://test.txt");
    }

    //本身捕獲異常
    public void test2() {
        try {
            new FileInputStream("D://test.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally{
            //無論異常發沒發生都總會執行的部分,一般用來處理收尾工做,入內存清理,關閉流等等
        }
    }

    //本身主動建立異常對象並拋出
    public void test3() throws Exception {
        throw new Exception("拋出異常");
    }

}

  這裏很基礎,仍是說三點:ide

  ① 最好從英文詞性上區分throw和throws兩個關鍵字。前者是動詞,表明拋出,很明顯是用在方法內部,執行異常對象的拋出動做;後者是名詞,用在方法後面,用來聲明方法執行可能拋出的一個或多個異常,多個異常之間用逗號隔開;測試

  ② finally塊不是必須的,除非業務中有必需要執行的部分;若是有finally塊,那該部分語句不管方法是否發生異常甚至中途執行return終止方法,該部分都會獲得執行;finally塊中不能使用return,會形成異常丟失;this

  ③ 若是你對異常是該拋出和本身處理舉棋不定,那布衣博主告訴你一個原則:該背鍋背鍋,不能背就甩鍋!是的,異常和平常中的甩鍋行爲相似。當別人向你甩來的鍋若是你能背,那就接住大膽背鍋處理異常,否則就甩鍋吧給上層調用者處理。編碼

  異常體系

  打開JDK API 文檔,找到 lang包中 Throwable類,這就是Java異常的祖宗類了。你會發現異常家族體系至關龐大,但大而不亂,由於這祖宗也就兩個直接子類 Error 和 Exception。Error 一般指系統錯誤,程序員無需關心;Exception纔是須要拋出或者捕獲的異常的基類,其下有不少子類孫類,支系繁茂。對於Exception類型異常,又分了編譯期異常和運行時異常兩大類,前者是在編碼階段必須處理(捕獲或者拋出)的異常類型,不處理程序沒法正常編譯;後者不用主動處理,一般是程序邏輯上的異常,在程序運行時由虛擬機拋出。只需記住以下譜系圖便可:spa

  自定義異常

  簡單封裝

  Java標準類庫中的異常雖然已經不少了,可是那是標準庫中通用的異常狀況,不一樣項目會有不一樣的業務邏輯,這就須要咱們根據本身的業務邏輯來定義、處理本身的異常。最好的自定義方式是從跟本身業務處理意思最接近的異常類繼承,好比定義運行時異常能夠繼承RuntimeException,定義IO異常能夠繼承IOException。不過對異常情形限定得太窄其實也沒有必要了,直接繼承異常基類Exception便可:code

public class MyException extends Exception {
    public MyException() {
        super();
    }

    public MyException(String message) {
        super(message);
    }

    public MyException(String message, Throwable cause) {
        super(message, cause);
    }
}

  這樣簡單的繼承,只是屏蔽了底層的具體異常類,對外暴露的是和本身業務相關的語義化的異常類名而已,功能依舊是父類異常的功能。這樣的自定義異常顯然功能太父類化了。更多的狀況下,咱們但願異常類能有比父類更完備的功能,以幫助程序向客戶端調者反饋更友好的信息。這個時候要跳出異常的字面意思去理解Java的異常機制,不能簡單的認爲異常就是發生了不想看到的錯誤,而是把異常當作一種控制流,是程序流程處理的一部分,控制着個人程序在狀況1 時走哪一步,在狀況2下又該執行哪一步。好比經過JNA調用底層動態庫獲取硬件信息,因爲程序運行的不可預見性,Java程序員和底層語言開發者之間會根據返回值約定一些異常情形,好比 0 表明什麼,1 表明什麼,諸如此類:對象

    public void func(int result) throws MyException1 ,MyException2,MyException3{
        switch (result){
            case 1:throw new MyException1();
            case 2:throw new MyException2();
            case 3:throw new MyException3();
            ...
        }
    }

  像上面這種,利用窮舉的方式寫代碼確定是很不明智的,更多的時候,咱們會採用枚舉與自定義異常相結合的方式,來處理異常的流程控制,以更好的發揮自定義異常的自定義做用。blog

  異常與枚舉

   先定義約定的異常情形枚舉:繼承

//異常狀態枚舉
public enum ErrorCode {
    SUCCESS(0, "成功"),
    NOTFOUND(1, "未找到驗證設備"),
    READFAIL(2, "讀取驗證設備失敗"),
    OVERDUE(3, "驗證設備已過時"),
    UNKNOWN(4, "未知緣由的失敗");

    int code;
    String msg;

    ErrorCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    //根據狀態碼獲取狀態信息
    public static ErrorCode getErrorCode(int code) {
        for (ErrorCode errorCode : values()) {
            if (errorCode.code == code) {
                return errorCode;
            }
        }
        return null;
    }

    @Override
    public String toString() {
        return "ErrorCode{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                '}';
    }
}

  再定義本身的異常類:

public class LibException extends Exception {

    private int code;
    private ErrorCode errorCode;


    public ErrorCode getErrorCode() {
        return errorCode;
    }


    LibException(int code) {
        this.code = code;
        this.errorCode = ErrorCode.getErrorCode(code);
    }

    public int getCode() {
        return code;
    }

    public LibException(String message) {
        super(message);
    }

    public LibException(String message, Throwable cause) {
        super(message, cause);
    }

}

    經過枚舉和自定義異常的結合,便能在程序中動態的根據錯誤碼反饋給上層調用者友好的異常信息。測試:

public class Test {
    public static void chenbenbuyi(int result) throws LibException {
        if(result>=0&&result<=4)throw new LibException(result);
        System.out.println("result: "+result);
    }

    public static void main(String[] args) {
        try {
            chenbenbuyi(3);
        } catch (LibException e) {
                System.err.println("錯誤碼:"+e.getCode()+" 錯誤信息:"+e.getErrorCode().getMsg());
        }
    }
}

  友好輸出反饋:

相關文章
相關標籤/搜索