異常處理是 Java 程式健壯性的基石。掌握 JDK 內建異常體系,並能根據業務需求設計自訂異常,是進階開發者的必備技能。本文系統梳理 java.lang 異常階層,並示範自訂異常的最佳實踐模式。
所有異常繼承自 java.lang.Throwable,主要分為兩大分支:
代表 JVM 層面的嚴重問題(如 OutOfMemoryError, StackOverflowError),通常不可恢復,應用程式不應嘗試捕捉處理。
分為受檢異常與非受檢異常:
| 類別 | 特徵 | 常見範例 | 處理方式 |
|---|---|---|---|
| 受檢異常 (Checked Exception) | 繼承 Exception 但非 RuntimeException;編譯器強制要求 try-catch 或 throws 聲明 | IOException, SQLException, ClassNotFoundException | 預期可恢復的錯誤,必須顯式處理 |
| 非受檢異常 (Unchecked Exception) | 繼承 RuntimeException;編譯器不強制檢查 | NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException, IllegalArgumentException | 程式邏輯錯誤,應透過修正代碼避免,而非捕捉 |
InsufficientBalanceException 取代通用的 RuntimeException,讓呼叫端明確知曉業務失敗原因。DataAccessException,Service 層轉為 BusinessException,Controller 統一映射 HTTP 狀態碼。/**
* 業務異常基類:攜帶錯誤代碼與動態訊息
*/
public class BizException extends RuntimeException {
private final int code;
public BizException(int code, String message) {
super(message);
this.code = code;
}
public BizException(int code, String message, Throwable cause) {
super(message, cause);
this.code = code;
}
public int getCode() { return code; }
}
/**
* 具體業務異常:餘額不足
*/
public class InsufficientBalanceException extends BizException {
public InsufficientBalanceException(String accountId, double balance, double amount) {
super(1001, String.format("帳戶 %s 餘額 %.2f 不足以支付 %.2f", accountId, balance, amount));
}
}
/**
* 使用範例:轉帳服務
*/
public class TransferService {
public void transfer(String from, String to, double amount) {
Account fromAcc = accountRepo.findById(from);
if (fromAcc.getBalance() < amount) {
// 直接拋出業務異常,無需捕捉 SQLException 等底層異常
throw new InsufficientBalanceException(from, fromAcc.getBalance(), amount);
}
// ... 扣款邏輯
}
}
message、cause、code 組合,保留堆疊追蹤鏈。final,執行緒安全。Exception 結尾;模組前綴區分域(如 OrderException, PaymentException)。IllegalArgumentException, IllegalStateException)即可,切勿為每個錯誤建立類別。自訂異常繼承自 Throwable,常用方法:
getMessage():詳細描述getLocalizedMessage():本地化描述(可覆寫)getCause():根因異常(鏈式追蹤關鍵)printStackTrace():輸出堆疊到標準錯誤流getStackTrace():程式化存取堆疊幀(StackTraceElement[])善用內建異常處理通用錯誤,關鍵業務流程引入語義豐富的自訂異常,並配合全域異常處理器(@ControllerAdvice / @ExceptionHandler)實現統一錯誤回應,能顯著提升系統可維護性與排錯效率。