Java中的析構方法finalize__Java

來源:互聯網
上載者:User
Java中的析構方法finalize

在C++程式設計中有建構函式與解構函式的概念,並且是記憶體管理技術中相當重要的一部分,而在Java語言中只有構造器(也可以稱為建構函式)的概念,卻沒有析構器或解構函式的概念。這是因為,理論上JVM負責對象的析構(銷毀與回收)工作。也就是上面講到的記憶體回收的概念。那麼Java語言中是否真的不存在與C++中解構函式職能類似的方法。其實Java語言中的finalize 方法與C++語言中的解構函式的職能就極為類似。finalize方法是Java語言根基類Object類中所包含的一個方法,這個方法是保護類型的方法(protected),由於在Java應用中開發的所有類都為Object的子類,因此使用者類都從Object對象中隱式地繼承了該方法。因此,我們在Java類中可以調用其父類的finalize方法,並且可以覆蓋自身繼承來的finalize方法。雖然我們可以在一個Java類中調用其父類的finalize方法,但是由於finalize方法沒有自動實現遞迴調用,我們必須手動實現,因此finalize函數的最後一個語句通常是super.finalize()語句。通過這種方式,我們可以實現從下到上finalize的迭代調用,即先釋放使用者類自身的資源,然後再釋放父類的資源。通常我們可以在finalize方法中釋放一些不容易控制,並且非常重要的資源,例如:一些I/O的操作,資料的串連。這些資源的釋放對整個應用程式是非常關鍵的。

finalize方法最終是由JVM中的記憶體回收行程調用的,由於記憶體回收行程調用finalize的時間是不確定或者不及時的,調用時機對我們來說是不可控的,因此,有時我們需要通過其他的手段來釋放程式中所佔用的系統資源,比如自己在類中聲明一個destroy()方法,在這個方法中添加釋放系統資源的處理代碼,當你使用完該對象後可以通過調用這個destroy()方法來釋放該對象內部成員佔用的系統資源。雖然我們可以通過調用自己定義的destroy()方法釋放系統資源,但是還是建議你最好將對destroy()方法的調用放入當前類的finalize()方法體中,因為這樣做更保險,更安全。在類深度繼承的情況下,這種方法就顯得更為有效了,我們可以通過遞迴調用destroy的方法在子類被銷毀的時候釋放父類所佔用的資源,例如下面的代碼:

1.原始基類A

public class A {

      Object a = null;

      public A() {

          a = new Object();

          System.out.println("建立a對象");

      }

      protected void destroy() {

         System.out.println("釋放a對象");

         a = null;

         // 釋放自身所佔用的資源

         …

      }

      protected void finalize() throws java.lang.Throwable {

         destroy();

         // 遞迴調用超類中的finalize方法

         super.finalize(); 

      }

  

}

2.一級子類B

public  class B extends A {

    Object b = null;

    public B() {

          b = new Object();

          System.out.println("建立b對象");

    }

    protected void destroy() {

         b = null;

         // 釋放自身所佔用的資源

         System.out.println("釋放b對象");

         super.destroy();

    }

    protected void finalize() throws java.lang.Throwable {

         destroy();

         // 遞迴調用超類中的finalize方法

         super.finalize(); 

    }

  

}

3.二級子類C

public class C extends B {

    Object c = null;

    public C() {

     c = new Object();

         System.out.println("建立c對象");

    }

    protected void destroy() {

         c = null;

         // 釋放自身所佔用的資源

         System.out.println("釋放c對象");

         super.destroy();

    }

    protected void finalize()throws java.lang.Throwable {

         destroy();

         // 遞迴調用超類中的finalize方法

         super.finalize(); 

    }

  

}

上面的三個類的繼承關係是非常明晰的:A->B->C,類A是原始基類(這是一種習慣叫法),類B繼承了類A,類C又繼承了類B。其實類A並不是真正意義上的原始基類,上面我們已經提到過Java語言中的原始基類是Object類,儘管我們並沒有顯式的聲明,但這已經是系統約定俗成的了。

為了簡單清楚地說明問題,我們在這三個類中分別聲明了3個方法,用來論證上面所講解的知識點,在類A的構造器中我們初始化了一個對象a,在destroy方法中通過a = null;釋放其自身所佔用的資源。並且在finalize方法中,我們調用了destroy方法用來釋放其自身所佔用的資源,然後調用其超類Object的finalize方法,這是我們以上所提到的“雙保險”的記憶體釋放方法;類B與類C的結構與類A極為相似,它們除了釋放自身所佔用的資源外,它們還在其對應的方法中調用其超類的destroy方法與finalize方法,用來釋放超類所佔用的資源。如在類B中調用其超類A的destroy方法與finalize方法與在類C中調用其超類B的destroy方法與finalize方法。但是類A與類B、類C有一點不同,那就是在其destroy方法中沒有super.destroy()語句,這是因為其超類Object並沒有destroy方法。下面看一下當我們調用初始化與銷毀類C時,會有什麼樣的情況發生。以下是調用完成這個過程的測試類別Test的原始碼:

public class Test {

    c = null;

    public Test () {

         c = new C();

    }

    public static void main(String args[]) {

         MyClass me = new MyClass();

         me.destroy();

         }

    protected void destroy () {

         if (c != null) {

              c.destroy();

         }else {

             System.out.println("c對象已被釋放");

         }  

    }  

}

編譯執行Test.java:

> javac Test.java

> java Test

下面是這個程式的運行結果:

建立a對象

建立b對象

建立c對象

釋放c對象

釋放b對象

釋放a對象

我們注意到當在Test類中初始化類C的對象時,其構造器產生了遞迴調用,並且是由基類開始依次調用、初始化成員對象的,而當調用C類對象的destroy方法時系統同樣產生了遞迴調用,但調用的順序卻與初始化調用的順序完全相反,釋放資源的調用順序是由子類開始的,依次調用其超類的資源釋放方法destroy()。由此可見,我們在設計類時應儘可能地避免在類的預設構造器中建立、初始化大量的對象。一個原因是在執行個體化自身的情況下,造成較大的資源開銷;另一個原因是其子類在被執行個體化時,也同樣會帶來較大的系統資源開銷。因為即使我們沒有想調用父類的構造器建立大量無用的對象(至少有時候這些對象對我們是沒有意義的),但是系統會自動建立它們,而這些操作與過程對於我們來說是隱含的。為了防止上述情況的發生,造成不必要的記憶體資源浪費,我們應當盡量不在類的構造器中建立、初始化大量的對象或執行某種複雜、耗時的運算邏輯。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.