首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 異常處理最佳實踐:檢查性異常恢復與非檢查性異常防禦

     編輯:Java 相關知識

異常體系速覽

  • Checked Exception(檢查性異常):繼承 Exception 但非 RuntimeException,編譯器強制處理,代表可預期、可恢復的運行時情況(如 IO 錯誤、網絡超時)
  • Unchecked Exception(非檢查性異常):繼承 RuntimeException 或 Error,編譯器不強制處理,代表編程錯誤(如空指針、數組越界、參數非法)

檢查性異常:提供健壯恢復機制

不應單純拋出或吞沒,而應在運行時嘗試恢復。示例:重試機制

public class Recover {
    protected int current = 0;
    protected boolean accept = false;

    public void passing() throws NotBigEnoughException {
        if (current > 2) accept = true;
        else throw new NotBigEnoughException("reject " + current);
    }

    public static void main(String[] args) {
        Recover re = new Recover();
        while (!re.accept) {
            try { re.passing(); }
            catch (NotBigEnoughException e) {
                System.out.println(e.getMessage());
                re.current++; // 恢復動作:遞增嘗試
            }
        }
        System.out.println("accept " + re.current);
    }
}
// 輸出: reject 0 → reject 1 → reject 2 → accept 3

繼承時的異常聲明規則

  • 覆寫方法:子類拋出的異常 必須是父類聲明異常的子集(即更具體或不拋出)
  • 構造方法:子類聲明的異常 必須包含父類聲明的異常(即更廣泛)

違規示例與兩種修正方案

// 父類
public void passing() throws NotBigEnoughException { ... }

// 子類嘗試新增 UnknowException → 編譯錯誤
public void passing() throws NotBigEnoughException, UnknowException { ... } // 錯誤

// 方案一:內部捕獲並恢復,不再拋出
public void passing() {
    while (!passed()) {
        try { super.passing(); }
        catch (NotBigEnoughException e) { increment(); }
    }
}

// 方案二:新增方法 fortifiedPassing(),捕獲父類異常後按業務邏輯轉換
public void fortifiedPassing() throws NotBigEnoughException, UnknowException {
    try { super.passing(); }
    catch (NotBigEnoughException e) {
        if (current >= 0) throw e;
        else throw new UnknowException("unknown state: " + current);
    }
}

RuntimeException 與異常包裝

  • 代表編程錯誤,應在開發/測試階段修復,而非運行時捕獲
  • 未捕獲到達 main() 會自動打印堆棧並退出
  • 包裝策略:捕獲檢查性異常後不知如何處理時,包裝為 RuntimeException 拋出,調用鏈無需聲明 throws,由全局異常處理器統一記錄/展示
public void fortifiedPassing() { // 無 throws 聲明
    try { super.fortifiedPassing(); }
    catch (NotBigEnoughException | UnknowException e) {
        throw new RuntimeException(e); // 保留原始異常為 cause
    }
}
// 調用者無需 try-catch,異常冒泡至頂層處理器

總結原則

  1. 檢查性異常 → 設計恢復邏輯(重試、降級、補償)
  2. 非檢查性異常 → 修復代碼缺陷,勿捕獲掩蓋
  3. 異常轉換 → 保留原始異常為 cause,保證診斷鏈完整
  4. 繼承規則 → 嚴格遵循 Liskov 替換原則的異常約束
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved