異常處理是健壯軟體的基石。Java 採用物件導向的異常模型,以 Throwable 為根,建立嚴謹的錯誤分類與傳遞機制。本文深入剖析異常體系架構、捕獲流程、多重捕獲語法,並提供企業級開發實戰建議。
Java 異常處理由五大關鍵字構成:
try {
// 高風險操作:IO、網路、資料庫、型別轉換等
riskyOperation();
} catch (SpecificException1 e) {
// 處理特定異常 1
handleSpecific1(e);
} catch (SpecificException2 e) {
// 處理特定異常 2,可選擇重新拋出
throw e;
} catch (Exception e) {
// 兜底處理:記錄日誌、轉換為自訂異常
log.error("Unexpected error", e);
throw new BusinessException("操作失敗", e);
} finally {
// 資源釋放:關閉流、連線、鎖等
closeResources();
}
java.lang.Object
└─ java.lang.Throwable
├─ java.lang.Error // 嚴重系統錯誤,應用不應捕獲
│ ├─ OutOfMemoryError
│ ├─ StackOverflowError
│ └─ NoClassDefFoundError
└─ java.lang.Exception // 應用可捕獲處理
├─ java.lang.RuntimeException // 非受檢異常,編譯器不強制處理
│ ├─ NullPointerException
│ ├─ IllegalArgumentException
│ ├─ IndexOutOfBoundsException
│ └─ ClassCastException
└─ 受檢異常 // 編譯器強制 try-catch 或 throws
├─ IOException
├─ SQLException
├─ ClassNotFoundException
└─ 自訂業務異常
| 類別 | 代表 | 處理策略 | 典型場景 |
|---|---|---|---|
| Error | OOM、StackOverflow | 不捕獲,讓程式崩潰並記錄日誌,由監控系統告警 | JVM 級資源耗盡、類別載入失敗 |
| RuntimeException | NPE、非法參數、越界 | 預防為主(防禦性程式設計),關鍵處可捕獲轉換 | 程式邏輯缺陷、空指標、型別轉換錯誤 |
| 受檢異常 | IO、SQL、網路 | 強制處理:捕獲轉換、向上拋出、或包裝為業務異常 | 外部資源不可控失敗(檔案不存在、DB 斷線) |
當方法未捕獲異常時,異常沿呼叫堆疊向上傳播:
public class UncaughtDemo {
public static void main(String[] args) {
methodA(); // 未捕獲,傳播至 main
}
static void methodA() { methodB(); }
static void methodB() {
int x = 1 / 0; // 拋出 ArithmeticException
}
}
輸出:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at UncaughtDemo.methodB(UncaughtDemo.java:10)
at UncaughtDemo.methodA(UncaughtDemo.java:8)
at UncaughtDemo.main(UncaughtDemo.java:4)
預設處理器列印堆疊追蹤並終止執行緒。生產環境應配置 Thread.setDefaultUncaughtExceptionHandler 統一記錄日誌、上報監控。
// 合併處理無繼承關係的異常
try {
parseData(input);
} catch (IOException | ParseException | SQLException e) {
log.error("資料解析失敗", e);
throw new DataProcessException(e);
}
// ❌ 錯誤:父類別在前會遮蔽子類別
catch (Exception e) { ... }
catch (IOException e) { ... } // 永遠執行不到
// ✅ 正確:具體異常優先
catch (FileNotFoundException e) { ... }
catch (IOException e) { ... }
catch (Exception e) { ... }
System.exit()、OOM、原生代碼 Crash)stop() 強制終止(已棄用)throw new BizException("訂單建立失敗", originalException)AutoCloseable 的資源// try-with-resources 範例
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
// 業務邏輯
} catch (SQLException e) {
throw new DataAccessException("查詢失敗", e);
} // 自動關閉 rs、stmt、conn,即使發生異常
catch (Exception e) { } 或只 e.printStackTrace()Java 異常機制以 Throwable 為根,區分 Error、RuntimeException、受檢異常三大類,配合 try-catch-finally 與 try-with-resources 提供結構化錯誤處理。掌握異常體系、傳播規則、最佳實務,是編寫可維護、可診斷、高可用 Java 系統的必修課。