三個長相相似、語意迥異的關鍵字/方法,是面試高頻考點,也是日常開發易混淆處。本文從語法層面、執行時機、JVM 實作、最佳實踐四個維度徹底釐清。
| 關鍵字/方法 | 類別 | 作用對象 | 核心語意 | 執行時機 |
|---|---|---|---|---|
final | 修飾符 | 類、方法、變量、參數 | 不可變/不可繼承/不可覆寫 | 編譯期/類載入期 |
finally | 程式塊 | try-catch 結構 | 無論是否異常必執行清理碼 | 運行期 (try 結束前) |
finalize() | Object 方法 | 物件實例 | GC 前釋放非記憶體資源 | GC 回收前 (不確定、已棄用) |
String, Integer)。private 方法隱式 final,無意義再加。try {
return 1;
} finally {
System.out.println("always"); // 必輸出
// return 2; // 若這裡 return,會覆蓋 try 的返回值(反模式)
}
不執行的極端情況: `System.exit(0)`、JVM Crash、無限迴圈/死鎖導致執行緒不退出 try。
// try-with-resources 自動關閉,優於手動 finally
try (InputStream in = Files.newInputStream(path);
BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
return br.readLine();
} // 隱式 finally 關閉資源,異常自動抑制
finalize(),JVM 會將其放入 **Finalizer 佇列**,由低優先級 **Finalizer 線程** 執行。// 1. try-with-resources (首選)
try (Resource r = acquire()) { ... }
// 2. Cleaner API (Java 9+,非阻塞、可預測)
public class ResourceHolder implements AutoCloseable {
private static final Cleaner cleaner = Cleaner.create();
private final Cleaner.Cleanable cleanable;
private final Resource resource;
public ResourceHolder(Resource r) {
this.resource = r;
this.cleanable = cleaner.register(this, r::close);
}
@Override public void close() { cleanable.clean(); }
}
// 3. PhantomReference + ReferenceQueue (底層控制)
public final class DatabaseConnection implements AutoCloseable {
private final Connection conn; // final 欄位:引用不可變
public DatabaseConnection(String url) throws SQLException {
this.conn = DriverManager.getConnection(url);
}
public void execute(String sql) { ... } // final 方法不可覆寫
@Override
public void close() throws SQLException { // try-with-resources 契約
if (conn != null && !conn.isClosed()) conn.close();
}
// ❌ 絕不覆寫 finalize()
}
final 是承諾(編譯期鎖死);finally 是保障(運行期兜底);finalize 是遺囑(GC 前念一次,不靠譜,別用)。
徹底理解三者差異,能寫出更安全、高效、符合現代 Java 風格的代碼。