Throwable
├── Error // 嚴重錯誤(OutOfMemoryError、StackOverflowError),不可恢復,不應捕獲
└── Exception // 可處理的異常
├── RuntimeException // 非受檢異常(空指針、越界、類轉換),編譯器不強制捕獲
└── 其他 // 受檢異常(IOException、SQLException),必須捕獲或拋出
try {
// 風險代碼
} catch (ExceptionType1 e) {
// 處理類型1
} catch (ExceptionType2 e) {
// 處理類型2
} finally {
// 無論是否異常必執行(資源清理)
}
// 自動關閉實現 AutoCloseable 的資源
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line = br.readLine();
} catch (IOException e) {
e.printStackTrace();
} // br 自動 close()
try {
risky();
} catch (ExceptionA e) {
throw new ExceptionB("處理失敗"); // 原始 e 丟失!
}
try {
risky();
} catch (ExceptionA e) {
ExceptionB eb = new ExceptionB("處理失敗");
eb.initCause(e); // 方式1
// 或 new ExceptionB("處理失敗", e) // 方式2(推薦)
throw eb;
}
輸出堆疊將包含 Caused by: ExceptionA,便於根因定位。
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("file.txt"));
// 業務邏輯
} catch (FileNotFoundException e) {
// 處理
} finally {
if (br != null) {
try { br.close(); } catch (IOException ignored) {}
}
}
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
// 處理結果集
} catch (SQLException e) {
// 記錄日誌、拋出業務異常
} finally {
// 逆序關閉
closeQuietly(rs);
closeQuietly(ps);
closeQuietly(conn);
}
| 陷阱 | 後果 | 規範 |
|---|---|---|
| catch 塊為空 | 吞噬異常,難以排查 | 至少記錄日誌:log.error("msg", e) |
| 捕獲 Exception/Throwable 過寬 | 掩蓋編程錯誤(如 NPE) | 捕獲具體受檢異常,RuntimeException 向上拋 |
| finally 中拋出異常 | 覆蓋 try/catch 中的原始異常 | finally 內部自行 try-catch,或用 try-with-resources |
| 異常用於流程控制 | 性能差、可讀性低 | 用條件判斷替代 |
// 業務異常:受檢,調用者必須處理
public class BusinessException extends Exception {
private final int errorCode;
public BusinessException(int code, String msg) { super(msg); this.errorCode = code; }
public BusinessException(int code, String msg, Throwable cause) { super(msg, cause); this.errorCode = code; }
}
// 系統異常:非受檢,向上拋至全局處理器
public class SystemException extends RuntimeException {
public SystemException(String msg, Throwable cause) { super(msg, cause); }
}
cause,構造器傳入或 initCause。