異常處理是健壯 Java 程式的基石。本文系統梳理異常體系、捕獲流程、檢查型與非檢查型異常區別、自定義異常設計,並給出實戰代碼範本。
Throwable
├── Error // JVM 嚴重錯誤(OutOfMemoryError、StackOverflowError),不應捕獲
└── Exception
├── RuntimeException (非檢查型) // NullPointerException、IndexOutOfBoundsException 等邏輯錯誤
└── 其他 Exception (檢查型) // IOException、SQLException、ClassNotFoundException 等環境錯誤
try 區塊:放置可能拋異常的「高風險代碼」,儘量精簡。catch 區塊:按子類優先、父類在後順序捕獲;可多重 catch,Java 7+ 支援多重捕獲 catch (IOException | SQLException e)。finally 區塊:無論是否拋異常、是否捕獲、是否 return,必定執行。適用於資源釋放(關閉流、釋放鎖)。try-with-resources (Java 7+):實作 AutoCloseable 的資源自動關閉,語法更簡潔安全。| 維度 | 檢查型 | 非檢查型 |
|---|---|---|
| 代表 | IOException, SQLException | NullPointerException, IllegalArgumentException |
| 編譯器強制 | 必須 catch 或 throws | 不強制 |
| 發生階段 | 運行時環境問題 | 程式邏輯缺陷 |
| 處理策略 | 預期可恢復,上層處理 | 修正代碼邏輯預防 |
// 業務異常基類
public class BizException extends Exception {
private final String errorCode;
public BizException(String code, String msg) { super(msg); this.errorCode = code; }
public String getErrorCode() { return errorCode; }
}
// 具體業務異常
public class InsufficientBalanceException extends BizException {
public InsufficientBalanceException(String acctId, double amt) {
super("BIZ_001", "帳戶 " + acctId + " 餘額不足,需 " + amt);
}
}
// 使用場景
public void withdraw(String acctId, double amt) throws InsufficientBalanceException {
if (balance < amt) throw new InsufficientBalanceException(acctId, amt);
balance -= amt;
}
public static void main(String[] args) {
double sum = 0;
for (int i = 0; i < args.length; i++) {
try {
sum += Double.parseDouble(args[i]);
} catch (NumberFormatException e) {
System.err.println("忽略非數字參數: " + args[i]);
}
}
System.out.println("Total: " + sum);
}
public class Stack {
private final Object[] elements;
private int size = 0;
public Stack(int capacity) { elements = new Object[capacity]; }
public void push(Object o) {
if (size == elements.length) throw new StackException("Stack overflow");
elements[size++] = o;
}
public Object pop() {
if (size == 0) throw new StackException("Stack underflow");
return elements[--size];
}
}
public class StackException extends Exception {
public StackException(String msg) { super(msg); }
}
catch (Exception e) {} 吞噬異常。throws 中聲明檢查型異常,形成契約。try-with-resources 替代手動 finally 關閉資源。