【從基礎學 Java】異常機制

初識

代碼的世界和現實世界同樣,不會一路順風,起碼不會像咱們想象中的那麼順利。寫代碼的是人,人的思惟存在侷限性,這種侷限性,體如今代碼中,就是漏洞。假若一段程序在生產環境中崩潰,勢必讓人十分惱火。這種讓人頭大的狀況就是異常的一種。html

Java 是這樣定義異常的:java

異常指的是,那些在程序運行過程當中,中斷正常的指令流程的事件。

實際上,異常還會在如下場景中發生:程序員

  • 用戶輸入錯誤,如:輸入不符合程序預期
  • 設備錯誤,如:網線斷開鏈接
  • 物理限制,如:內存不足

而咱們並不但願程序由於上述狀況掛掉,而是但願程序可以在遇到異常時,巧妙地處理以後,繼續運行下去。oracle

所幸,Java 提供了一套機制,用於在程序程序出錯(出現異常)時,進行:編碼

  • 報告錯誤
  • 保存工做結果
  • 讓用戶以更完善的方式退出程序

亦即:異常處理機制。顧名思義,該機制用於對程序運行中不正常的狀況進行處理。
簡單來講,Java 中的異常處理是:當異常發生時,運行時系統逆着方法的調用棧(call stack)去尋找可以處理這種異常的東西。spa

以一個把字符串轉換成整數的方法爲例:設計

public Integer stringToNumber(String strToFormat){
    Integer targetNum;
    try{
        targetNum = new Integer(strToFormat);
    }catch(NumberFormatException e){
        targetNum = DEFAULT_NUM;
    }
    return targetNum;
}

在上述代碼中,當 strToFormat 不能轉化成一個整形數時,就轉化成一個默認的值。NumberFormatException 發生時,方法當即終止。控制權被交由 catch 代碼塊,也就是異常處理器(exception hanlder)。代碼雖然簡單,卻包含了 Java 異常處理的通常步驟。code

異常分類

在 Java 中,全部的異常派生於 Throwable 接口。這些異常,又被分爲 ErrorException。這兩類異常,又衍生了一些子類。下面的圖片,描述了 Java 的異常體系圖:orm

Java 異常體系圖

不過,咱們應當把精力放在 RuntimeException 上,由於「全部的運行時異常,都是程序員的問題」。這類異常,又被叫作未檢查異常,一般交由 JVM 處理。相對應的,那些咱們知道可能會出現問題、,被叫作已檢查的異常。這類異常須要開發者手動向上級拋出,直到 JVM 級別,或者在調用方法時使用 try-catch 處理。htm

通常來講,在寫一個方法時,要儘量聲明全部已檢查異常,經過內部邏輯控制,避免未檢查(運行時)異常。

異常捕獲

在編碼過程當中,若是方法的檢查異常被精心設計,那麼咱們只管拋出異常便可。可是,一旦調用方法的地方沒有對這種可能出現的異常進行處理,那麼程序就會終止。因此,要對異常進行捕獲操做,正如以前的字符串轉數字的方法同樣。

根據經驗,程序中應該捕獲那些知道如何處理的異常,把「職責」外的異常,交給方法的調用者去處理。下面是一個異常捕獲流程的示例代碼:

modifier returnType someMethod(type1 param1, type2 param2) throws Exception1, Exceptio2{
    
        try{
            ① // 某些操做
            return returnType value;
        }catch(Exceptionx | Exceptiony e){
            ② // 處理異常
        }catch(Excpetion1 e1){
            ③ throw new Excption1(e1);
        }catch(Exception e2){
            ④ throw e2;
        }finally{
            ⑤ // 一些操做
            return returnType mockValue;
        }
        
}

在上述代碼中,① 中進行操做,捕獲了 Exeptionx 或者 Exceptiony 時,② 進行異常處理;捕獲了 Exception1 時, ③ 把該異常包裝;捕獲了 Exception 2 時,④ 直接拋出異常;不管有無異常發生,⑤ 都會執行。

上面的代碼還有一個問題,就是 finally 代碼中包含返回值。有如下規則:

  • try 代碼塊中包含 return 語句,finally 語句中的代碼也會被執行;若 finally 中也包含 return 語句,則會替代 try 中的語句

使用異常的技巧

  • 不要過度細分異常,能用一個 try 塊處理的儘可能用一個,而後按層次捕獲異常,下面的代碼是被建議的:
try{
    // 某些操做
}catch(SomeException1 e1){
    // 異常 1 的處理
}catch(SomeException2 e2){
    // 異常 2 的處理
}
  • 適當地轉化異常,如:能夠把一個 NumberFormatException 轉化成自定義的異常
  • 遇到異常狀況,能夠更加嚴格一點。如:拋出 EmptyStackException 比 NullPointerException 更加語義化
  • 學會把異常傳遞,即:「早拋出,晚捕獲」
相關文章
相關標籤/搜索