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

Java 異常處理完全指南:從入門到最佳實踐

     編輯:Java 相關知識

異常體系全景圖

java.lang.Throwable
├── Error (嚴重錯誤,不可恢復,如 OutOfMemoryError、StackOverflowError)
└── Exception (異常,可捕獲處理)
    ├── RuntimeException (運行時異常,非受檢,編譯器不強制捕獲)
    │   ├── NullPointerException
    │   ├── ArrayIndexOutOfBoundsException
    │   ├── IllegalArgumentException
    │   └── ...
    └── 受檢異常 (Checked Exception,編譯器強制捕獲或拋出)
        ├── IOException
        ├── SQLException
        ├── ClassNotFoundException
        └── ...

核心 API 與常用手法

1. 獲取完整堆疊追蹤

try {
    // 風險代碼
} catch (Exception e) {
    e.printStackTrace(); // 輸出至標準錯誤流,含異常類型、訊息、完整調用棧
    // 或寫入日誌框架:log.error("業務失敗", e);
}

2. 異常處理三大鐵律

  1. 禁止用異常控制業務流程:異常成本高(填充堆疊追蹤),且語義不清。用 if/else、Optional、狀態機替代。
  2. 優先使用標準異常:IllegalArgumentException、IllegalStateException、NullPointerException 等語義明確,減少自定義類膨脹。
  3. 謹慎選擇 Checked vs Unchecked:
    • 調用者能具體恢復 → Checked Exception(如 IOException 可重試)。
    • 調用者無法恢復/屬編程錯誤 → RuntimeException(如參數非法、狀態不符)。

標準 try-catch-finally 結構

try {
    // 正常業務邏輯
    doBusiness();
} catch (SpecificException1 e) {
    // 處理特定異常1
    handle1(e);
} catch (SpecificException2 e) {
    // 處理特定異常2
    handle2(e);
} catch (Exception e) {
    // 兜底:記錄未預期異常,防止吞噬
    log.error("未知錯誤", e);
    throw new RuntimeException(e); // 或轉換為統一業務異常
} finally {
    // 清理資源:關流、釋放鎖、歸還連接
    // 必定執行(除非 JVM 退出)
    closeResources();
}

進階技巧

1. 異常鏈:保留原始原因

try {
    jdbcTemplate.query(sql);
} catch (SQLException e) {
    // 包裝為業務異常,保留根因
    throw new DataAccessException("查詢失敗", e);
}

JDK 1.4+ 內建支援 Throwable(initCause),printStackTrace() 會遞歸列印完整鏈路。

2. try-with-resources (JDK 7+)

// 實作 AutoCloseable 的資源自動關閉,無需 finally
try (Connection conn = dataSource.getConnection();
     PreparedStatement ps = conn.prepareStatement(sql);
     ResultSet rs = ps.executeQuery()) {
    return parse(rs);
} // 編譯器自動生成關閉代碼,即使拋異常也會關閉

3. 多重捕獲

catch (IOException | SQLException e) {
    log.error("IO 或 SQL 錯誤", e);
}

4. 自定義異常設計

// 業務異常基類(RuntimeException 系)
public class BizException extends RuntimeException {
    private final String errorCode;
    public BizException(String code, String msg) { super(msg); this.errorCode = code; }
    public String getErrorCode() { return errorCode; }
}

// 使用
throw new BizException("USER_NOT_FOUND", "用戶不存在: " + userId);

效能與陷阱避坑

  • 避免在循環/高頻路徑拋異常:填充堆疊追蹤極耗 CPU,熱點路徑用返回碼/Optional。
  • 別吞噬異常:catch (Exception e) {} 或只 log.info(e) 會掩蓋 Bug,至少 log.error + 重拋。
  • finally 中別拋異常:會掩蓋 try/catch 中的原始異常,資源關閉用 IOUtils.closeQuietly() 或 try-with-resources。
  • 序列化異常:跨進程傳遞異常需實作 Serializable,注意 serialVersionUID。

總結

異常處理的核心哲學是「失敗快速、失敗明確、失敗安全」:讓錯誤盡早暴露(編譯期或啟動期)、異常語義清晰指向問題本質、資源在任何路徑下都能正確釋放。掌握體系結構、善用標準異常、遵循 try-with-resources 與異常鏈,即能寫出健壯、可維護的 Java 代碼。

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