異常機制將「正常業務邏輯」與「錯誤處理邏輯」分離,避免層層 if-else 判斷返回碼。本文深入講解異常拋捕執行流程、自定義異常構造器陷阱、printStackTrace 堆棧原理、throws 聲明規則與實戰建議。

throw new XxxException())。catch 塊 (按聲明順序,子類優先)。
4. 執行 catch 塊處理邏輯。
5. 不返回 拋出點繼續執行,而是執行 catch 後的代碼 (或 finally 後)。
try {
// 可能拋出 NullPointerException、ArrayIndexOutOfBoundsException、IOException
} catch (NullPointerException e) { // 具體異常優先
// 處理空指針
} catch (ArrayIndexOutOfBoundsException e) {
// 處理越界
} catch (IOException e) {
// 處理 IO
} catch (Exception e) { // 兜底
// 記錄未知異常
}
// ❌ 錯誤:自定義字段 msg,未調用父類構造器
class MyException extends Exception {
String msg;
public MyException(String msg) { this.msg = msg; }
public void printMsg() { System.out.println(msg); }
}
// ✅ 正確:調用 super(msg) 將信息傳給父類 Throwable 的 detailMessage 字段
class MyException2 extends Exception {
public MyException2(String msg) { super(msg); }
}
// 測試
try { throw new MyException("msg1"); } catch (MyException e) { System.out.println(e.getMessage()); } // 輸出 null!
try { throw new MyException2("msg2"); } catch (MyException2 e) { System.out.println(e.getMessage()); } // 輸出 msg2
結論:自定義異常必須調用 super(message),否則 getMessage() 返回 null,printStackTrace() 也無詳細信息。
JVM 為每個線程維護一個調用棧 (棧幀:方法、行號、局部變量)。異常對象創建時捕獲當前棧快照 (fillInStackTrace()),printStackTrace() 遍歷輸出:
java.lang.NullPointerException
at com.demo.Test.methodB(Test.java:20)
at com.demo.Test.methodA(Test.java:15)
at com.demo.Test.main(Test.java:10)
at 全類名.方法名(文件名:行號),從拋出點向上到 main/線程入口。Caused by:鏈式異常 (包裹異常 throw new RuntimeException(e))。throws Exception1, Exception2。try-catch) 或繼續 throws 向上拋。throws 只能拋出父類方法聲明的異常或其子類 (里氏替換原則)。
public void readFile() throws OpenException, CloseException { // 聲明多個
if (open() == -1) throw new OpenException();
}
public static void main(String[] args) {
try { readFile(); }
catch (OpenException e) { e.printStackTrace(); }
catch (CloseException e) { e.printStackTrace(); }
}
catch (SQLException e) { throw new BizException("DB錯誤", e); } 保留原始堆棧。try-with-resources 自動關閉 AutoCloseable。log.error("操作失敗", e) 而非 e.printStackTrace(),支持異步輸出、結構化字段。@ControllerAdvice + @ExceptionHandler 統一返回錯誤碼、錯誤信息、追蹤 ID。