傳統 C 風格錯誤處理存在三大缺陷:程式設計師易忽略錯誤檢查、主邏輯與錯誤處理混雜導致可讀性差、錯誤處理常被遺忘。Java 透過編譯器強制機制、try-catch-finally 結構分離主邏輯與錯誤處理、方法簽名聲明異常(throws)三大特性徹底解決這些問題。
throws 宣告可檢查異常(Checked Exception)。throw new ExceptionType() 建立並拋出異常物件。try-catch 或 try-catch-finally 處理,或繼續向上拋出(throws)。JVM 維護先進後出的方法呼叫堆疊。異常發生時,建立包含型別與程式狀態的 Exception 物件,沿堆疊向上尋找匹配的 catch 區塊。若全程未捕獲,JVM 終止程式並列印堆疊追蹤。
java.lang.Throwable
├── java.lang.Error // 系統內部錯誤(虛擬機錯誤、連結錯誤),不可恢復
└── java.lang.Exception // 程式異常,可捕獲處理
├── RuntimeException // 非受檢異常:邏輯錯誤(空指標、越界、除零),應修正程式而非捕獲
└── 其他 Exception 子類 // 受檢異常:外部資源錯誤(IO、SQL、網路),必須捕獲或聲明
try:主邏輯區塊,至少需一個 catch 或 finally。catch:按順序匹配異常型別,**子類必須前於父類**;可用 printStackTrace()、getMessage()、toString() 獲取資訊。finally:**無論是否發生異常皆執行**(除非 System.exit() 或 JVM 崩潰),適用於資源清理(關閉檔案、釋放連線)。| 異常 | 觸發場景 | 類別 |
|---|---|---|
ArrayIndexOutOfBoundsException | 陣列索引越界 | RuntimeException |
NullPointerException | 使用 null 參考 | RuntimeException |
NumberFormatException | 字串轉數字失敗 | RuntimeException |
ClassCastException | 型別轉換失敗 | RuntimeException |
FileNotFoundException | 檔案不存在 | IOException (Checked) |
IllegalArgumentException | 方法參數非法 | RuntimeException |
Exception(受檢)或 RuntimeException(非受檢)。MyException()、MyException(String msg)、MyException(String msg, Throwable cause)。Exception 結尾,遵循 JDK 慣例。assert booleanExpression; // 簡單形式
assert booleanExpression : errorMessageExpr; // 帶訊息形式
// 編譯:javac AssertDemo.java
// 執行(啟用斷言):java -ea AssertDemo
// 執行(停用斷言,預設):java AssertDemo
isValid())。switch-default 分支理論上不可達處放置 assert false。絕不可用斷言檢查 public 方法參數,因生產環境斷言關閉會導致驗證失效。應使用 if-else 拋出 IllegalArgumentException。
| 維度 | 斷言 | 異常 |
|---|---|---|
| 目的 | 驗證程式假設、文檔化不變量 | 處理運行時錯誤、外部資源失效 |
| 啟用控制 | JVM 參數 -ea/-da | 永遠啟用 |
| 適用對象 | 內部邏輯、私有方法、測試代碼 | 公共 API、IO 操作、使用者輸入 |