<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    weidagang2046的專欄

    物格而后知致
    隨筆 - 8, 文章 - 409, 評(píng)論 - 101, 引用 - 0
    數(shù)據(jù)加載中……

    理解finalize()-析構(gòu)函數(shù)的替代者

    理解finalize()-析構(gòu)函數(shù)的替代者

    by Tim Gooch

    在許多方面,Java 類似于 C++。Java 的語法非常類似于 C++,Java 有類、方法和數(shù)據(jù)成員;Java 的類有構(gòu)造函數(shù); Java 有異常處理。

    但是,如果你使用過 C++ 會(huì)發(fā)現(xiàn) Java 也丟掉一些可能是你熟悉的特性。這些特性之一就是析構(gòu)函數(shù)。取代使用析構(gòu)函數(shù),Java 支持finalize() 方法。

    在本文中,我們將描述 finalize() 與 C++ 析構(gòu)函數(shù)的區(qū)別。另外,我們將創(chuàng)建一個(gè)簡(jiǎn)單的 Applet 來演示 finalize() 是如何工作的。

    最終的界限

    與 Java 不同,C++ 支持局部對(duì)象(基于棧)和全局對(duì)象(基于堆)。因?yàn)檫@一雙重支持,C++ 也提供了自動(dòng)構(gòu)造和析構(gòu),這導(dǎo)致了對(duì)構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用,(對(duì)于堆對(duì)象)就是內(nèi)存的分配和釋放。

    在 Java 中,所有對(duì)象都駐留在堆內(nèi)存,因此局部對(duì)象就不存在。結(jié)果,Java 的設(shè)計(jì)者覺得不需要析構(gòu)函數(shù)(象 C++ 中所實(shí)現(xiàn)的)。

    取而代之,Java 定義了一個(gè)特殊的方法叫做finalize() ,它提供了 C++ 析構(gòu)函數(shù)的一些功能。但是,finalize() 并不完全與 C++ 的析構(gòu)函數(shù)一樣,并可以假設(shè)它會(huì)導(dǎo)致一系列的問題。finalize() 方法作用的一個(gè)關(guān)鍵元素是 Java 的垃圾回收器。

    垃圾回收器

    在 C/C++、Pascal和其他幾種多種用途的編程語言中,開發(fā)者有責(zé)任在內(nèi)存管理上發(fā)揮積極的作用。例如,如果你為一個(gè)對(duì)象或數(shù)據(jù)結(jié)構(gòu)分配了內(nèi)存,那么當(dāng)你不再使用它時(shí)必須釋放掉該內(nèi)存。

    在 Java 中,當(dāng)你創(chuàng)建一個(gè)對(duì)象時(shí),Java 虛擬機(jī)(JVM)為該對(duì)象分配內(nèi)存、調(diào)用構(gòu)造函數(shù)并開始跟蹤你使用的對(duì)象。當(dāng)你停止使用一個(gè)對(duì)象(就是說,當(dāng)沒有對(duì)該對(duì)象有效的引用時(shí)),JVM 通過垃圾回收器將該對(duì)象標(biāo)記為釋放狀態(tài)。

    當(dāng)垃圾回收器將要釋放一個(gè)對(duì)象的內(nèi)存時(shí),它調(diào)用該對(duì)象的finalize() 方法(如果該對(duì)象定義了此方法)。垃圾回收器以獨(dú)立的低優(yōu)先級(jí)的方式運(yùn)行,只有當(dāng)其他線程掛起等待該內(nèi)存釋放的情況出現(xiàn)時(shí),它才開始運(yùn)行釋放對(duì)象的內(nèi)存。(事實(shí)上,你可以調(diào)用System.gc() 方法強(qiáng)制垃圾回收器來釋放這些對(duì)象的內(nèi)存。)

    在以上的描述中,有一些重要的事情需要注意。首先,只有當(dāng)垃圾回收器釋放該對(duì)象的內(nèi)存時(shí),才會(huì)執(zhí)行finalize()。如果在 Applet 或應(yīng)用程序退出之前垃圾回收器沒有釋放內(nèi)存,垃圾回收器將不會(huì)調(diào)用finalize()。

    其次,除非垃圾回收器認(rèn)為你的 Applet 或應(yīng)用程序需要額外的內(nèi)存,否則它不會(huì)試圖釋放不再使用的對(duì)象的內(nèi)存。換句話說,這是完全可能的:一個(gè) Applet 給少量的對(duì)象分配內(nèi)存,沒有造成嚴(yán)重的內(nèi)存需求,于是垃圾回收器沒有釋放這些對(duì)象的內(nèi)存就退出了。

    顯然,如果你為某個(gè)對(duì)象定義了finalize() 方法,JVM 可能不會(huì)調(diào)用它,因?yàn)槔厥掌鞑辉尫胚^那些對(duì)象的內(nèi)存。調(diào)用System.gc() 也不會(huì)起作用,因?yàn)樗鼉H僅是給 JVM 一個(gè)建議而不是命令。

    finalize() 有什么優(yōu)點(diǎn)呢?

    如果finalize() 不是析構(gòu)函數(shù),JVM 不一定會(huì)調(diào)用它,你可能會(huì)疑惑它是否在任何情況下都有好處。事實(shí)上,在 Java 1.0 中它并沒有太多的優(yōu)點(diǎn)。

    根據(jù) Java 文檔,finalize() 是一個(gè)用于釋放非 Java 資源的方法。但是,JVM 有很大的可能不調(diào)用對(duì)象的finalize() 方法,因此很難證明使用該方法釋放資源是有效的。

    Java 1.1 通過提供一個(gè)System.runFinalizersOnExit() 方法部分地解決了這個(gè)問題。(不要將這個(gè)方法與 Java 1.0 中的System.runFinalizations() 方法相混淆。)不象System.gc() 方法那樣,System.runFinalizersOnExit() 方法并不立即試圖啟動(dòng)垃圾回收器。而是當(dāng)應(yīng)用程序或 Applet 退出時(shí),它調(diào)用每個(gè)對(duì)象的finalize() 方法。

    正如你可能猜測(cè)的那樣,通過調(diào)用System.runFinalizersOnExit() 方法強(qiáng)制垃圾回收器清除所有獨(dú)立對(duì)象的內(nèi)存,當(dāng)清除代碼執(zhí)行時(shí)可能會(huì)引起明顯的延遲。現(xiàn)在建立一個(gè)示例 Applet 來演示 Java 垃圾回收器和finalize() 方法是如何相互作用的。

    回收垃圾

    通過使用Java Applet Wizard 創(chuàng)建一個(gè)新的 Applet 開始。當(dāng)提示這樣做時(shí),輸入 final_things 作為 Applet 名,并選擇不要生成源文件注釋。

    接下來,在Java Applet Wizard 進(jìn)行第三步,不要選擇多線程選項(xiàng)。在第五步之前,根據(jù)需要修改 Applet 的描述。

    當(dāng)你單擊Finish 后,Applet Wizard 將生成一個(gè)新的工作空間,并為該項(xiàng)目創(chuàng)建缺省的 Java 文件。從列表 A 中選擇適當(dāng)?shù)拇a輸入(我們已經(jīng)突出顯示了你需要輸入的代碼)。

    當(dāng)你完成代碼的輸入后,配置Internet 瀏覽器將System.out 的輸出信息寫到Javalog.txt 文件中。(在IE 選項(xiàng)對(duì)話框的高級(jí)頁面中選擇起用 Java Logging。)

    編譯并運(yùn)行該 Applet。然后,等待 Applet 運(yùn)行(你將在狀態(tài)欄中看到 Applet 已啟動(dòng)的信息),退出瀏覽器,并打開Javalog.txt 文件。你將會(huì)發(fā)現(xiàn)類似于下列行的信息:

            1000 things constructed

            0 things finalized

    正如你能夠看到的那樣,建立了1,000個(gè)對(duì)象仍然沒有迫使垃圾回收器開始回收空間,即使在 Applet 退出時(shí)也沒有對(duì)象被使用。

    現(xiàn)在,刪除在stop() 方法第一行中的注釋符以起用System.gc() 方法。再次編譯并運(yùn)行該 Applet ,等待 Applet 完成運(yùn)行,并退出瀏覽器。當(dāng)你再次打開Javalog.txt 文件,你將看到下列行:

            1000 things constructed

            963 things finalized

    這次,垃圾回收器認(rèn)為大多數(shù)對(duì)象未被使用,并將它們回收。按順序,當(dāng)垃圾回收器開始釋放這些對(duì)象的內(nèi)存時(shí),JVM 調(diào)用它們的finalize() 方法。

    繼承finalize()?

    順便,如果你在類中定義了finalize() ,它將不會(huì)自動(dòng)調(diào)用基類中的方法。在我們討論了finalize() 與 C++ 的析構(gòu)函數(shù)的不同點(diǎn)后,對(duì)這個(gè)結(jié)論不會(huì)驚訝,因?yàn)闉槟硞€(gè)類定制的清除代碼另一個(gè)類不一定會(huì)需要。

    如果你決定要通過派生一個(gè)類的finalize() 方法來調(diào)用基類中的finalize() 方法,你可以象其他繼承方法一樣處理。

            protected void finalize()

            {

              super.finalize();

              // other finalization code...

            }

    除了允許你控制是否執(zhí)行清除操作外,這個(gè)技術(shù)還使你可以控制當(dāng)前類的finalize() 方法何時(shí)執(zhí)行。

    結(jié)論

    然而有益的是,Java 的自動(dòng)垃圾回收器不會(huì)失去平衡。作為便利的代價(jià),你不得不放棄對(duì)系統(tǒng)資源釋放的控制。不象 C++ 中的析構(gòu)函數(shù),Java Applet 不會(huì)自動(dòng)執(zhí)行你的類中的finalize() 方法。事實(shí)上,如果你正在使用 Java 1.0,即使你試圖強(qiáng)制它調(diào)用finalize() 方法,也不能確保將調(diào)用它。

    因此,你不應(yīng)當(dāng)依靠finalize() 來執(zhí)行你的 Applet 和應(yīng)用程序的資源清除工作。取而代之,你應(yīng)當(dāng)明確的清除那些資源或創(chuàng)建一個(gè)try...finally 塊(或類似的機(jī)制)來實(shí)現(xiàn)。

    列表 A: final_things.java

    import java.applet.*;

    import java.awt.*;

     

    class thing

    {

      public static int thingcount = 0;

      public static int thingfinal = 0;

     

      public thing()

      {

        ++thingcount;

      }

     

     

      protected void finalize()

      {

        ++thingfinal;

      }

    }

     

    public class final_things extends Applet

    {

     

      public final_things()

      {

      }

     

      public String getAppletInfo()

      {

        return "Name: final_thing\r\n" +

               "Author: Tim Gooch\r\n" +

               "Created with Microsoft " +

               "Visual J++ Version 1.1";

      }

     

     

      public void init()

      {

          resize(320, 240);

     

      }

     

      public void destroy()

      {

      }

     

      public void paint(Graphics g)

      {

        g.drawString("Created with Microsoft" +

          "Visual J++ Version 1.1", 10, 20);

      }

     

      public void start()

      {

        while(thing.thingfinal < 1)

        {

          new thing();

        }

      }

      public void stop()

      {

        // System.gc();

        System.out.println(thing.thingcount +

          " things constructed");

        System.out.println(thing.thingfinal +

          " things finalized");

      }

    }

    轉(zhuǎn)自:http://www.microsoft.com/china/msdn/archives/technic/develop/vj/0515c.asp

    posted on 2005-05-12 11:53 weidagang2046 閱讀(253) 評(píng)論(0)  編輯  收藏 所屬分類: Java

    主站蜘蛛池模板: 久久亚洲精精品中文字幕| 在线中文高清资源免费观看| 中文字幕高清免费不卡视频| MM1313亚洲国产精品| 亚洲熟妇AV日韩熟妇在线| 亚洲色图激情文学| 国产精品亚洲一区二区麻豆| 亚洲AV成人一区二区三区在线看| 亚洲精品福利你懂| 亚洲欧洲无码AV不卡在线| 亚洲欧美综合精品成人导航| 亚洲综合成人婷婷五月网址| 亚洲国产欧美一区二区三区| 亚洲av午夜电影在线观看| 美女被羞羞网站免费下载| 亚州**色毛片免费观看| 国产免费人成视频尤勿视频| a级毛片免费播放| 国产成人免费视频| 97性无码区免费| 日韩欧美一区二区三区免费观看| 女人18毛片水真多免费看 | 亚洲国产成人手机在线观看| 亚洲av无码成人精品区一本二本 | 亚洲a在线视频视频| 久久精品九九亚洲精品| 2020年亚洲天天爽天天噜| 亚洲人成网站18禁止| 黄色片网站在线免费观看| 国产在线观看免费av站| 99re免费在线视频| 处破痛哭A√18成年片免费| 免费人成视频在线观看视频| 亚洲精品无码精品mV在线观看| 亚洲欧洲国产日韩精品| 在线观看日本亚洲一区| 日本激情猛烈在线看免费观看| 毛片免费在线观看| 成年丰满熟妇午夜免费视频| 国产精品亚洲不卡一区二区三区 | 国产一区二区三区无码免费|