Java 7 引入 **try-with-resources** (TWR) 語法,徹底改變資源管理方式:實現 `AutoCloseable` 的資源在 try 塊結束時自動關閉,且**異常抑制機制**保證主要異常不被 finally 中的關閉異常掩蓋。本文通過對比代碼深度剖析 TWR 的語法糖本質、異常傳播語義與最佳實踐。
// 傳統模式:冗長、易漏關、異常掩蓋
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
fis = new FileInputStream(file);
isr = new InputStreamReader(fis, "UTF-8");
br = new BufferedReader(isr);
// 讀取邏輯
return lines;
} catch (IOException e) {
throw new RuntimeException("Read failed", e);
} finally {
if (br != null) {
try { br.close(); } catch (IOException e) { e.printStackTrace(); } // 異常被吞或打印,掩蓋主異常
}
}
核心缺陷:若 try 塊拋出異常 A,finally 中 `close()` 又拋出異常 B,**異常 B 會覆蓋異常 A** 向外傳播,導致根因丟失,排查極難。
// Java 7+ 標準寫法:資源聲明在 try()
try (FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(isr)) {
// 讀取邏輯
return lines;
} catch (IOException e) {
throw new RuntimeException("Read failed", e);
}
// 無需 finally,編譯器自動插入關閉代碼
// 伪代碼展示編譯器生成邏輯
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(isr);
Throwable primary = null; // 主異常
try {
// 用戶代碼
return lines;
} catch (Throwable t) {
primary = t;
throw t;
} finally {
if (primary != null) {
try { br.close(); } catch (Throwable suppressed) {
primary.addSuppressed(suppressed); // 關閉異常被抑制附加到主異常
}
} else {
br.close(); // 正常結束直接拋出關閉異常
}
}
這是 TWR 最大的工程價值:**異常鏈完整性**。
| 接口 | 包 | 拋出異常 | 適用場景 |
|---|---|---|---|
Closeable | `java.io` | `IOException` | IO 資源 (流、Channel、Reader/Writer) |
AutoCloseable | `java.lang` | `Exception` | **所有資源** (JDBC Connection/Statement/ResultSet、Lock、自定義資源) |