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

Java 異常處理機制深度解析:從異常體系、拋捕機制到自定義異常最佳實踐

     編輯:Java 綜合教學

異常本質:問題的對象化封裝

Java 將「運行時問題」封裝為對象,所有異常類繼承自 Throwable,具備 可拋性:可被 throw (拋對象) 與 throws (聲明拋類) 操作。

異常體系全景圖

Throwable
├── Error                 // JVM 級嚴重錯誤,不可恢復 (OOM, StackOverflow)
└── Exception             // 應用級異常,可捕獲處理
    ├── RuntimeException  // 運行時異常 (非受檢),編譯器不強制處理
    │   ├── NullPointerException
    │   ├── IllegalArgumentException
    │   └── IndexOutOfBoundsException
    └── 受檢異常         // 編譯期強制 try/catch 或 throws
        ├── IOException
        ├── SQLException
        ├── ClassNotFoundException
        └── 自定義業務異常

拋捕機制核心規則

關鍵字位置作用異常類型
throw方法體內拋出異常對象單個
throws方法簽名聲明拋出異常類多個,逗號分隔

受檢 vs 非受檢 選擇原則

  • 受檢異常:調用者合理預期且能處理的情況 (如文件不存在、數據庫連接失敗)。強制編譯期處理,保證不被忽略。
  • 運行時異常:編程錯誤導致 (空指針、越界、參數非法),調用者無法預期處理,建議修復代碼而非捕獲。

三種處理模式

// 1. 完整模式:try-catch-finally
try {
    // 高風險代碼
} catch (IOException e) {
    // 處理邏輯
} finally {
    // 必執行邏輯:關流、釋放鎖、清理資源
    // 注意:System.exit(0) 會跳過 finally
}

// 2. 僅捕獲:try-catch
try { ... } catch (Exception e) { ... }

// 3. 僅清理:try-finally (Java 7+ 建議用 try-with-resources)
try (InputStream in = new FileInputStream("a.txt")) {
    // 使用 in
} // 自動調用 in.close()

自定義異常最佳實踐

// 業務異常基類:受檢異常,強制調用者感知
public class BusinessException extends Exception {
    private final int errorCode;
    public BusinessException(int errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }
    public int getErrorCode() { return errorCode; }
}

// 具體業務異常:語義化命名
public class InsufficientBalanceException extends BusinessException {
    public InsufficientBalanceException(String msg) { super(1001, msg); }
}

public class UserNotFoundException extends BusinessException {
    public UserNotFoundException(String msg) { super(1002, msg); }
}

// 運行時異常基類:系統級/編程錯誤
public class SystemException extends RuntimeException {
    public SystemException(String msg, Throwable cause) { super(msg, cause); }
}

自定義異常設計原則

  1. 繼承正確父類:業務異常 extends Exception,系統異常 extends RuntimeException。
  2. 攜帶錯誤碼:便於前端國際化、監控告警、日志檢索。
  3. 保留堆疊:構造器調用 super(message, cause) 保留原始原因鏈。
  4. 文檔化:Javadoc 標註 @throws 條件與處理建議。

異常處理黃金法則

  1. 具體捕獲: catch (IOException e) 而非 catch (Exception e),避免吞噬非預期異常。
  2. 早拋早捕: 在最能處理的層級捕獲,不要層層 throws 到 Controller 再統一處理 (除非統一錯誤碼轉換)。
  3. 不吞噬異常: catch (Exception e) { } 絕對禁止,至少 log.error("", e)。
  4. 資源必關閉: IO、連接、鎖、線程池 — 統一用 try-with-resources 或 finally。
  5. 異常轉換保留原因: throw new BusinessException(..., e) 而非 throw new BusinessException(...)。
  6. 避免用異常控制流程: 如 try { map.get(key); } catch { return default; } 應改用 map.getOrDefault()。

實戰代碼片段

// 矩形構造器:參數校驗拋運行時異常 (編程錯誤)
public class Rectangle implements Shape {
    private final int len, wid;
    public Rectangle(int len, int wid) {
        if (len <= 0 || wid <= 0)
            throw new IllegalArgumentException("矩形邊長必須 > 0");
        this.len = len; this.wid = wid;
    }
    public void getArea() { System.out.println(len * wid); }
}

// 圓構造器:同理
public class Circle implements Shape {
    private final int r;
    public Circle(int r) {
        if (r <= 0) throw new IllegalArgumentException("半徑必須 > 0");
        this.r = r;
    }
    public void getArea() { System.out.println(Math.PI * r * r); }
}

// 調用方:無需 try-catch,讓運行時異常冒泡到全局異常處理器
public class Test {
    public static void main(String[] args) {
        new Circle(-8).getArea();  // 直接拋出 IllegalArgumentException
        System.out.println("over"); // 不會執行
    }
}

總結

Java 異常機制的核心價值在於 強制錯誤顯性化:受檢異常強制 API 使用者面對可能失敗的操作,運行時異常暴露編程邏輯缺陷。掌握 異常分類選擇、自定義異常設計、try-with-resources 資源管理、全局異常處理器統一響應,是編寫健壯、可維護 Java 系統的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved