異常處理是編寫健壯 Java 程式的基石。本文系統梳理 Java 異常體系、內置異常類、捕獲處理機制、finally、throws/throw、自定義異常及常見陷阱,幫助開發者建立規範的異常處理體系。
| 類別 | 代表 | 特點 | 處理要求 |
|---|---|---|---|
| 受檢異常 (Checked Exception) | IOException、ClassNotFoundException | 編譯期強制檢查,通常由外部因素導致(文件不存在、網絡中斷) | 必須 try-catch 或 throws 聲明 |
| 運行時異常 (Runtime Exception) | NullPointerException、ArrayIndexOutOfBoundsException | 編譯期不檢查,通常由邏輯錯誤導致(空指針、越界) | 建議通過代碼邏輯預防,而非單純捕獲 |
| 錯誤 (Error) | OutOfMemoryError、StackOverflowError | JVM 層面嚴重問題,應用無法恢復 | 一般不捕獲,需優化代碼或調優 JVM |
java.lang.Throwable
├── java.lang.Error
└── java.lang.Exception
├── java.io.IOException
├── java.lang.RuntimeException
│ ├── NullPointerException
│ ├── IllegalArgumentException
│ └── ...
└── 其他受檢異常...
try {
// 風險代碼
} catch (IOException e) {
// 處理 IO 異常
} catch (SQLException e) {
// 處理 SQL 異常
} finally {
// 清理資源(關閉流、釋放鎖),無論是否異常都會執行
}
FileNotFoundException 必須在 IOException 前)。catch (IOException | SQLException e)。throws:方法簽名聲明拋出的異常,將責任上傳給調用者。throw:主動拋出異常實例:throw new BusinessException("餘額不足")。try {
connection = dataSource.getConnection();
// 業務邏輯
} catch (SQLException e) {
log.error("數據庫操作失敗", e);
throw new DaoException(e);
} finally {
// 確保連接歸還池中,防止洩漏
if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
}
陷阱: finally 中使用 return 會吞噬 try/catch 中拋出的異常,切勿如此使用。
Exception(受檢),系統/邏輯異常繼承 RuntimeException。message、cause、message+cause。public class InsufficientFundsException extends Exception {
private final double shortage;
public InsufficientFundsException(double shortage) {
super(String.format("餘額不足,缺口 %.2f 元", shortage));
this.shortage = shortage;
}
public double getShortage() { return shortage; }
}
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException(amount - balance);
}
balance -= amount;
}
| 異常 | 觸發場景 |
|---|---|
NullPointerException | 調用 null 對象方法/屬性 |
ClassCastException | 強制轉型失敗 |
IllegalArgumentException | 方法參數不合法 |
NumberFormatException | 字符串轉數字格式錯誤 |
IndexOutOfBoundsException | 數組/集合索引越界 |
ConcurrentModificationException | 迭代時併發修改集合 |
catch (Exception e) 大餐。cause:throw new BizException("下單失敗", e)。try-with-resources (Java 7+) 自動關閉實現 AutoCloseable 的資源。e.printStackTrace() 直寫控制台。異常處理不是「捕獲並吞噬」,而是「識別、轉換、上下文豐富、資源安全釋放、可觀測」。建立分層異常體系(系統異常 vs 業務異常),配合全局異常處理器(如 Spring @ControllerAdvice),才能構建可維護、可排查的生產級應用。