異常處理是構建健壯系統的基石。第 12 章從異常哲學切入,系統闡述拋捕機制、異常規範、自定義異常、finally 清理、棧追蹤、異常鏈、受檢/非受檢異常抉擇、構造器異常處理、替代方案。本文提煉核心精華與實戰指南。
「在問題發生點,你可能不知道怎麼處理,但你知道不能繼續執行。將問題拋給更高層級、有資格決策的上下文。」
// 拋出
throw new IOException("網絡中斷"); // 帶信息的構造器
// 捕獲
try {
riskOperation();
} catch (IOException e) {
// 處理或轉換
throw new BusinessException("業務失敗", e); // 異常鏈:保留根因
} finally {
cleanup(); // 必執行清理
}
String message。Throwable 為根,兩大分支:
OutOfMemoryError、StackOverflowError),不捕獲。Exception(非 RuntimeException),編譯器強制 try-catch 或 throws。例:IOException、SQLException。RuntimeException,編譯器不強制。例:NullPointerException、IllegalArgumentException。代表編程錯誤,應通過代碼邏輯預防。catch 順序:子類在前,父類在後,否則編譯錯誤(不可達代碼)。catch (IOException | SQLException e) 合併處理。finally:無論是否異常、是否 return,必執行(除非 System.exit()、JVM 崩潰、無限循環)。| 陷阱 | 代碼 | 後果 | 規避 |
|---|---|---|---|
| 吞噬異常 | try { throw new A(); } finally { return 1; } | 異常 A 丟失,調用者感知不到 | finally 中絕不 return/throw/break/continue |
| 資源關閉異常掩蓋 | finally { in.close(); out.close(); } | in.close() 拋異常導致 out.close() 不執行 | 各自 try-catch 包裹,或用 try-with-resources |
| 維度 | 受檢異常 | 非受檢異常 |
|---|---|---|
| 適用場景 | 可恢復的業務/外部故障(文件不存在、網絡超時、數據庫死鎖) | 編程錯誤、不可恢復的系統故障、框架內部錯誤 |
| 優勢 | 編譯器強制處理,API 文檔化 | 代碼簡潔、不污染方法簽名、適合冒泡到全局處理器 |
| 劣勢 | 樣板代碼多、易被吞噬、擴散到調用鏈 | 易被忽視、運行時才發現 |
| 現代趨勢 | Spring/框架層轉為非受檢,由全局 @ControllerAdvice 統一處理 | 業務代碼仍建議受檢,明確錯誤語義 |