public String test() {
try {
throw new RuntimeException("原始異常");
} finally {
return "finally 返回值"; // 吞噬異常,調用者感知不到異常!
}
}
// 調用 test() 正常返回 "finally 返回值",異常丟失
鐵律:finally 中絕不使用 return、throw、break、continue 控制流程語句。
class Resource implements AutoCloseable {
@Override public void close() throws Exception {
throw new Exception("關閉失敗");
}
}
try (Resource r = new Resource()) {
throw new Exception("業務異常");
} catch (Exception e) {
// e = 業務異常
// e.getSuppressed() = [關閉失敗異常]
System.out.println("主異常: " + e.getMessage());
for (Throwable s : e.getSuppressed()) {
System.out.println("被抑制: " + s.getMessage());
}
}
優勢:主異常不被掩蓋,關閉異常不丟失,通過 getSuppressed() 可訪問。
try {
// 底層操作
} catch (SQLException e) {
// 包裝為業務異常,保留原始原因
throw new BusinessException("用戶保存失敗", e); // 构造器傳入 cause
}
// 異常鏈打印
e.printStackTrace(); // 自動打印完整鏈路
// 或手動遍歷
Throwable cause = e;
while (cause != null) {
System.out.println(cause.getClass() + ": " + cause.getMessage());
cause = cause.getCause();
}
// 線程池任務異常捕獲
ExecutorService executor = Executors.newFixedThreadPool(2);
Future> future = executor.submit(() -> {
throw new RuntimeException("任務異常");
});
try {
future.get(); // 這裡會拋出 ExecutionException,cause 是原始異常
} catch (ExecutionException e) {
Throwable realCause = e.getCause(); // 獲取真實異常
log.error("任務失敗", realCause);
}
// 全局異常處理器
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
log.error("線程 {} 未捕獲異常: ", thread.getName(), throwable);
});
// 異常類實現 Serializable 才能跨 JVM 傳輸
public class BizException extends Exception implements Serializable {
private static final long serialVersionUID = 1L; // 必須顯式聲明
// 否則反序列化時可能 InvalidClassException
}
public class Config {
static {
// 靜態塊拋異常 → 包裝為 ExceptionInInitializerError
loadConfig(); // 可能拋 IOException
}
}
// 使用時
try {
Config.class.getDeclaredField("x");
} catch (ExceptionInInitializerError e) {
Throwable root = e.getCause(); // 獲取真實原因 (IOException)
}
StackOverflowError:遞歸過深、循環調用,不可捕獲恢復,需修正算法OutOfMemoryError:堆/元空間耗盡,極難恢復,可嘗試釋放緩存後重試關鍵操作Error,不屬於受檢異常,通常不應捕獲
// -ea 啟用斷言
assert condition : "錯誤信息";
// 失敗拋 AssertionError,屬於 Error,生產環境建議關閉斷言
| 場景 | 核心原則 | 關鍵 API |
|---|---|---|
| finally 控制流 | 嚴禁 return/throw | 無 |
| 資源關閉異常 | TWR 自動抑制 | getSuppressed() |
| 異常包裝 | 保留 cause 鏈 | new Ex(msg, cause) |
| 異步任務異常 | future.get() 解包 | ExecutionException.getCause() |
| 異常序列化 | 實現 Serializable + serialVersionUID | 無 |
| 類初始化失敗 | 捕獲 ExceptionInInitializerError | getCause() |
| OOM/StackOverflow | 不捕獲,修正代碼/配置 | JVM 參數調優 |
精通異常處理邊界條件,是編寫穩健、可診斷、可維護 Java 系統的關鍵能力。