try {
// 高風險操作
} catch (IOException | SQLException | TimeoutException ex) {
// 統一處理邏輯
logger.error("操作失敗", ex);
throw ex; // 重新拋出
}
ex 型別為聯集型別,僅能存取共同父類方法Exception | IOException 編譯錯誤)final,ex 不可重新賦值編譯器生成單一 catch 區塊,而非多個重複區塊,減少類檔案體積。
// JDK 6 必須宣告拋出 Exception,過於寬泛
public void process() throws Exception {
try {
riskyOperation();
} catch (Exception ex) {
logAndCleanup();
throw ex; // 方法簽名必須 throws Exception
}
}
public void process() throws IOException, SQLException { // 精確宣告
try {
riskyOperation();
} catch (final Exception ex) { // final 關鍵!
logAndCleanup();
throw ex; // 編譯器推導實際動態型別
}
}
final 保證 ex 引用不變public void complex() throws IOException, SQLException {
try {
step1(); // throws IOException
step2(); // throws SQLException
} catch (final Exception ex) {
if (ex instanceof IOException) {
handleIO((IOException) ex);
} else if (ex instanceof SQLException) {
handleSQL((SQLException) ex);
}
throw ex; // 精確重新拋出 IOException 或 SQLException
}
}
| 場景 | JDK 6 寫法 | JDK 7+ 寫法 | 收益 |
|---|---|---|---|
| 多異常統一處理 | 多個 catch 區塊重複代碼 | 單一 multi-catch 區塊 | 代碼減少 60%+,維護性提升 |
| 統一記錄後重拋 | throws Exception 污染簽名 | final catch + 精確 throws | 異常透明傳遞,呼叫端可精確捕獲 |
| 包裝異常轉換 | 捕獲 → 包裝 → 拋出新異常 | 同樣需包裝,但可精確宣告 | 保持異常鏈完整 |
final,獲得精確異常型別推導Exception 或 Throwable,除非頂層攔截器throw new BizException("msg", cause) 而非丟失 cause// JDK 14+ instanceof 模式匹配
catch (final Exception ex) {
if (ex instanceof IOException io) handleIO(io);
else if (ex instanceof SQLException sql) handleSQL(sql);
throw ex;
}
// JDK 21+ 未命名變數 (JEP 443)
try { risky(); }
catch (IOException | SQLException _) { // 不關心異常物件
logError();
throw _; // 隱含 final 重新拋出
}
Java 7 的 Multi-catch 解決「多 catch 重複代碼」,Final Rethrow 解決「精確異常透傳」。兩者結合,使異常處理更簡潔、型別安全、對呼叫端友善。雖 Final Rethrow 使用頻率較低,但在框架開發、中介軟體、異常轉換層極具價值。