InputStream is = null;
try {
is = new FileInputStream("file.txt");
// 讀取邏輯
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close(); // 可能拋異常,需嵌套 try-catch
} catch (IOException e) {
e.printStackTrace();
}
}
}
問題:樣板代碼多、資源關閉易漏、異常遮蓋 (close() 異常掩蓋原始異常)。
// 自動資源管理 (ARM)
try (InputStream is = new FileInputStream("file.txt");
OutputStream os = new FileOutputStream("out.txt")) {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
AutoCloseable (或 Closeable)close() 保證被調用,即使前面拋異常close() 拋出的異常被抑制,附加在原始異常上try (ResourceA a = new ResourceA(); // close() 拋出 ExceptionA
ResourceB b = new ResourceB()) { // close() 拋出 ExceptionB
throw new Exception("原始異常");
} catch (Exception e) {
// e = 原始異常
// e.getSuppressed() = [ExceptionB, ExceptionA] (逆序)
for (Throwable suppressed : e.getSuppressed()) {
System.out.println("被抑制異常: " + suppressed);
}
}
close() 異常不丟失但不干擾主流程Throwable.getSuppressed() 獲取被抑制異常數組// 傳統
catch (IOException e) { ... }
catch (SQLException e) { ... }
// 合並 (管道符分隔)
catch (IOException | SQLException | TimeoutException e) {
e.printStackTrace(); // e 類型為公共父類 (Exception)
}
e 隱式為 final,不可重賦值// 傳統:方法簽名需聲明 Exception
public void method() throws Exception {
try { risky(); } catch (Exception e) { throw e; }
}
// JDK 7:編譯器精確推導實際拋出類型
public void method() throws IOException, SQLException {
try { risky(); } catch (Exception e) { throw e; }
// 編譯器知道只會拋 IOException 或 SQLException
}
// JDK 9+ 允許引用外部 final/等效 final 變量
InputStream is = Files.newInputStream(path);
try (is) { // 無需在括號中聲明
// 使用 is
} // 自動關閉 is
public class DbConnection implements AutoCloseable {
private Connection conn;
@Override public void close() throws SQLException {
if (conn != null) conn.close();
}
}
log.error("msg", e) 而非 log.error(e.getMessage())| 反模式 | 後果 | 正確做法 |
|---|---|---|
| catch 後不處理 (空 catch) | 異常吞沈,排查極難 | 至少記錄日誌或轉換拋出 |
| 捕獲 Exception/Throwable | 誤捕系統級錯誤 (OOM 等) | 捕獲具體檢查型異常 |
| finally 中 return | 掩蓋原始異常 | 不要在 finally 控制流程 |
| 資源關閉無保護 | 資源洩漏 | try-with-resources |
掌握現代 Java 異常處理特性,編寫出健壯、可維護、資源安全的代碼。