Effective Java代碼規則之八:避免使用終結器和清除器

1、解釋

終結器(finalizer)是不可預測的,通常是危險的,並且通常是不必要的。 它們的使用會導致不穩定的行為,性能不佳和可移植性問題。 終結器有一些有效用途,我們將在本項後面介紹,但作為一項規則,您應該避免使用它們。 從Java 9開始,終結器已被棄用,但它們仍被Java庫使用。 Java 9用清潔器(cleaner)替代終結器。

清潔器比終結器危險性小,但仍然不可預測,緩慢且通常不必要。

終結器和清除器的問題如下:

  • Java 語言規範不僅不保證終結器或者清除器會被及時地執行,而且根本就不保證它們會被執行;
  • 在執行終結器機制過程中,未捕獲的異常會被忽略,並且該對象的終結器機制也會終止;
  • 使用終結器和清潔器機制會導致嚴重的性能問題。
  • 終結方法有一個嚴重的安全問題,它們為終結方法攻擊( finalizer attack ) 打開了類的大門。

2、優點

可以避免使用終結器和清除器帶來的問題。

3、缺點

可能會喪失使用終結器和清除器的一些好處:

  • 用終結器充當“安全網”

這樣做井不能保證終結器或者清除器會被及時地運行,但是遲一點釋放資源總比永遠不釋放要好(當close方法被忘記調用的時候)。

  • 終止非關鍵的本地資源

在JNI中,我們可以用清除器來釋放非關鍵的本地資源。如果要釋放關鍵本地資源,仍然要調用close方法。

4、最佳實踐

在實際工作中,如果類的對象中封裝的資源(例如文件或者線程)確實需要終止,應該怎麼做才能不用編寫終結器或者清除器呢?只需讓類實現AutoCloseable接口,在使用try-catch-resources語法創建的資源拋出異常後,JVM會自動調用close方法進行資源釋放,當正常退出時try-block時候也會調用close方法。

public class AutoCloseAbleClass implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("i am close");
}
public void dosomething() {
System.out.println("do something");
}
}

//使用try-catch-resources語法
try (AutoCloseAbleClass autoCloseable = new AutoCloseAbleClass()) {
autoCloseable.dosomething();
} catch (Exception e) {
e.printStackTrace();
}

Effective Java代碼規則之八:避免使用終結器和清除器

專業從事軟件研發工作多年,在軟件設計、開發、測試、研發管理等領域裡經驗豐富,感興趣的朋友可以關注我的頭條號,相信一定會有所收穫。

如果有軟件研發方面的問題,可以諮詢我。

謝謝!


分享到:


相關文章: