簡體   English   中英

為什么java.lang.Object中的finalize()方法受到“保護”?

[英]Why is the finalize() method in java.lang.Object “protected”?

出於好奇,

為什么將finalize()方法的訪問修飾符設置為protected 為什么不能public 有人可以向我解釋這背后的任何具體原因嗎?

另外,我知道finalize()方法僅被調用一次。 如果我在程序內部兩次調用它,會發生什么情況? 垃圾收集器會再次調用嗎?

private void dummyCall() {
    try {
        finalize();
        finalize();
    } catch (Throwable e) {
        e.printStackTrace();//NOT REACHES EXCEPTION
    }
}

我用另一個問題回答您的問題:

為什么finalize方法不應該受到保護?

通常,您應該嘗試使事物盡可能私密。 這就是封裝的全部內容。 否則,您可以將所有內容 public finalize不能是private (因為派生類應該能夠訪問它才能覆蓋它),因此它至少應該protected但是為什么在不希望使用時賦予更多訪問權限呢?


在更仔細地閱讀了您的評論之后,我想我現在明白了您的要點。 我認為您的意思是,由於所有內容都源自java.lang.Object並因此訪問其protected成員,因此將其public (或與此相關的java.lang.Object任何方法)沒有任何區別protected 我個人認為這是Java的設計缺陷。 這確實在C#中已修復。 問題不是為什么finalize受保護。 沒關系。 真正的問題是,您不應該能夠通過基類類型的對象引用來在基類中調用受保護的方法。 埃里克·利珀特(Eric Lippert)的博客條目討論了為什么允許這種方式訪問​​受保護成員不是一個好主意, 對此問題在“堆棧溢出”中作了進一步闡述

為什么finalize()方法的訪問修飾符被設置為保護狀態。 為什么不能公開?

它不是公共的,因為它不應被JVM之外的任何人調用。 但是,必須對其進行保護,以便需要定義其行為的子類可以覆蓋它。

如果我在程序中兩次調用它,內部會發生什么?

您可以隨意調用它,畢竟它只是一個方法。 但是,就像public static void main(String [] args) ,它對JVM有特殊的意義。

垃圾收集器會再次調用嗎?

  • finalize只能由gc調用,因此不需要公共訪問
  • finalize保證僅由gc調用一次,您自己調用它會破壞此保證,因為gc對此一無所知。
  • 任何壓倒一切的課程都可以將最終定稿公開,由於上述原因,我認為這是不好的
  • finalize不應包含太多代碼,因為finalize引發的任何異常都可能殺死gc的finalizer線程。

反對finalize()

  • 管理本機資源或需要調用dispose()或close()的任何資源可能會導致難以發現錯誤,因為這些錯誤僅在jvm內存不足時才被釋放,您應該手動釋放資源。 Finalize僅應用於調試資源泄漏或用於手動管理資源的工作過多的情況。
  • finalize將在gc的附加線程中調用,並可能導致資源鎖定等問題。
  • 像WeakReference和ReferenceQueue這樣的引用類是處理清除的另一種方法(相當復雜),並且可能與本機資源的finalize()一樣。

當心上面聲明中的錯誤,我有點累:-)

查看討論該鏈接

基本上,將它設為private是最有意義的,因為它只能由JVM(垃圾收集器)調用。 但是為了允許子類在其finalize()一部分中調用父finalize()方法,必須對其進行protected

編輯 -只是一般性的警告-由於沒有辦法確保調用它,因此通常不建議使用finalize()方法。盡管這並不意味着您永遠不會有使用它的方法-很少見。)

關於finalize()僅被調用一次的部分僅適用於來自GC的調用。 您可以想象該對象具有隱藏標志“ GC調用了finalize() ”,然后GC檢查該標志以了解如何處理該對象。 您自己手工調用finalize()不會對標志產生任何影響。

完成后,請閱讀Hans Boehm(以垃圾收集工作而聞名的文章 )。 這對完成工作大開眼界。 Boehm特別說明了為什么終止必須是異步的。 一個必然的結論是,雖然最終確定是一個強大的工具,但對於給定的工作而言,它很少是正確的工具。

它不是public (或默認訪問權限),因為它是在對象被垃圾回收時由JVM內部調用的,而不是由其他任何東西調用的。 而且它不是private因為它意味着要被覆蓋,並且您不能覆蓋私有方法。

如果我在程序中兩次調用它,內部會發生什么? 垃圾收集器會再次調用嗎?

可能是的,但是很難想象會有什么意義的情況finalize()的目的是在垃圾回收對象時進行清理。 而且它甚至還不能很好地完成工作,因此,您確實應該完全避免而不是進行試驗。

我認為finalize被保護的原因是,它可能被JDK中的某些類所覆蓋,而那些被覆蓋的方法被JVM調用。

當對象被收集時,JVM僅使用finalize()來清理資源。 一個類定義在集合上應該采取什么動作是合理的,它可能需要為此訪問super.finalize()。 外部進程調用finalize()確實沒有意義,因為外部進程無法控制何時收集對象。

另外,我知道finalize()方法僅被調用一次。 如果我在程序中兩次調用它,內部會發生什么?

您可能會在C ++〜析構函數的印象下問這個問題。 在Java中,finalize()方法沒有任何作用(例如清除內存)。 應該由垃圾收集器調用。 但反之亦然。

我建議您閱讀Joshua Bloch的“ Effective Java”中的相應章節。 它說使用終結器是一種不好的做法,可能會導致性能和其他問題,只有幾種情況下應該使用它們。 本章以以下幾句話開頭:

終結器是不可預測的,通常很危險,而且通常是不必要的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM