Java 異常模型爭議由來已久。本文指出:問題不在語言機制,而在類庫設計混淆了應變與故障兩類根本不同的失敗語義。通過將異常語義對齊業務與系統邊界,建立故障屏障與應變傳播雙軌架構,實現代碼簡潔、診斷完整、業務語義清晰的異常治理體系。
| 維度 | 應變 | 故障 |
|---|---|---|
| 語義 | 預期內的替代返回,屬於方法契約一部分 | 預期外的系統級錯誤,無法在當前上下文恢復 |
| 頻率 | 正常業務流程中會發生 | 極少發生,屬於「壞事」 |
| 處理者 | 直接調用者(上游業務邏輯) | 基礎設施/運維/開發人員(跨層) |
| 典型例 | 餘額不足、停付指令、庫存不足 | DB 掛掉、配置錯誤、網絡分區、Bug |
| 最佳映射 | 受檢異常(編譯器強制處理) | 非受檢異常(RuntimeException 子類) |
JDK 大量將故障(如 IOException、SQLException)建模為受檢異常,導致:
try-catch 污染,實際無法處理。FaultException extends RuntimeException(Java 1.4+ 支持異常鏈 initCause)。FaultException → 拋出。ExceptionHandler、Spring SimpleMappingExceptionResolver、Servlet Filter、AOP 切面)統一捕獲,完成:InsufficientFundsException、StopPaymentException。OverdraftProtection),調用者可直接決策(轉賬、拒絕、記賬)。故障屏障天然是橫切關注點。使用 AspectJ/Spring AOP:
FaultException 及其子類,執行統一處理邏輯。應變異常屬於業務邏輯一部分,通常不建議用 AOP 攔截,保持顯式傳播。
正確使用 Java 異常模型的關鍵在於語義分類而非語法偏好。將「應變」建模為受檢異常,「故障」建模為非受檢異常並交給故障屏障,配合 AOP 封裝橫切邏輯,即可獲得:業務代碼純淨、診斷信息完整、架構邊界清晰的異常治理體系。