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

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

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

    jimphei學習工作室

    jimphei學習工作室

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      23 隨筆 :: 0 文章 :: 1 評論 :: 0 Trackbacks

    11.4.3 對象的finalize()方法簡介

    當垃圾回收器將要釋放無用對象的內存時,先調用該對象的finalize()方法。如果在程序終止之前垃圾回收器始終沒有執行垃圾回收操作,那么垃圾回收器將始終不會調用無用對象的finalize()方法。在Java的Object祖先類中提供了protected類型的finalize()方法,因此任何Java類都可以覆蓋finalize()方法,在這個方法中進行釋放對象所占的相關資源的操作。

    Java虛擬機的垃圾回收操作對程序完全是透明的,因此程序無法預料某個無用對象的finalize()方法何時被調用。另外,除非垃圾回收器認為程序需要額外的內存,否則它不會試圖釋放無用對象占用的內存。換句話說,以下情況是完全可能的:一個程序只占用了少量內存,沒有造成嚴重的內存需求,于是垃圾回收器沒有釋放那些無用對象占用的內存,因此這些對象的finalize()方法還沒有被調用,程序就終止了。

    程序即使顯式調用System.gc()或Runtime.gc()方法,也不能保證垃圾回收操作一定執行,因此不能保證無用對象的finalize()方法一定被調用。

    11.4.4 對象的finalize()方法的特點

    對象的finalize()方法具有以下特點:

    垃圾回收器是否會執行該方法及何時執行該方法,都是不確定的。

    finalize()方法有可能使對象復活,使它恢復到可觸及狀態。

     垃圾回收器在執行finalize()方法時,如果出現異常,垃圾回收器不會報告異常,程序繼續正常運行。

    下面結合一個具體的例子來解釋finalize()方法的特點。例程11-13的Ghost類是一個帶實例緩存的不可變類,它的finalize()方法能夠把當前實例重新加入到實例緩存ghosts中。

    例程11-13 Ghost.java

    import java.util.Map;

    import java.util.HashMap;

    public class Ghost {

    private static final Map<String,Ghost> ghosts=new HashMap<String,Ghost>();

    private final String name;

    public Ghost(String name) {

    this.name=name;

    }

    public String getName(){return name;}

    public static Ghost getInstance(String name){

    Ghost ghost =ghosts.get(name);

    if (ghost == null) {

    ghost=new Ghost(name);

    ghosts.put(name,ghost);

    }

    return ghost;

    }

    public static void removeInstance(String name){

    ghosts.remove(name);

    }

    protected void finalize()throws Throwable{

    ghosts.put(name,this);

    System.out.println("execute finalize");

    //throw new Exception("Just Test");

    }

    public static void main(String args[])throws Exception{

    Ghost ghost=Ghost.getInstance("IAmBack"); //①

    System.out.println(ghost); //②

    String name=ghost.getName(); //③

    ghost=null; //④

    Ghost.removeInstance(name); //⑤

    System.gc(); //⑥

    //把CPU讓給垃圾回收線程

    Thread.sleep(3000); //⑦

    ghost=Ghost.getInstance("IAmBack"); //⑧

    System.out.println(ghost); //⑨

    }

    }

    運行以上Ghost類的main()方法,一種可能的打印結果為:

    Ghost@3179c3

    execute finalize

    Ghost@3179c3

    以上程序創建了3個對象:1個Ghost對象、1個常量字符串“IAmBack”及1個HashMap對象。當程序執行完main()方法的第③行時,內存中引用變量與對象之間的關系如圖11-9所示。

    圖11-9 Ghost對象與其他對象及引用變量的關系

    當執行完第④行時,ghost變量被置為null,此時Ghost對象依然被ghosts屬性間接引用,因此仍然處于可觸及狀態。當執行完第⑤行時,Ghost對象的引用從HashMap對象中刪除,Ghost對象不再被程序引用,此時進入可復活狀態,即變為無用對象。

    第⑥行調用System.gc()方法,它能提高垃圾回收器盡快執行垃圾回收操作的可能性。假如垃圾回收器線程此刻獲得了對CPU的使用權,它將調用Ghost對象的finalize()方法。該方法把Ghost對象的引用又加入到HashMap對象中,Ghost對象又回到可觸及狀態,垃圾回收器放棄回收它的內存。執行完第⑧行,ghost變量又引用這個Ghost對象。

    假如對finalize()做一些修改,使它拋出一個異常:

    protected void finalize()throws Throwable{

    ghosts.put(name,this);

    System.out.println("execute finalize");

    throw new Exception("Just Test");

    }

    程序的打印結果不變。由此可見,當垃圾回收器執行finalize()方法時,如果出現異常,垃圾回收器不會報告異常,也不會導致程序異常中斷。

    假如在程序運行中,垃圾回收器始終沒有執行垃圾回收操作,那么Ghost對象的finalize()方法就不會被調用。讀者不妨把第⑥行的System.gc()和第⑦行的Thread.sleep(3000)方法注釋掉,這樣更加可能導致finalize()方法不會被調用,此時程序的一種可能的打印結果為:

    Ghost@3179c3

    Ghost@310d42

    從以上打印結果可以看出,由于Ghost對象的finalize()方法沒有被執行,因此這個Ghost對象在程序運行期間始終沒有復活。當程序第二次調用Ghost.getInstance("IAmBack")方法時,該方法創建了一個新的Ghost對象。

    值得注意的是,以上例子僅僅用于演示finalize()方法的特性,在實際應用中,不提倡用finalize()方法來復活對象??梢园烟幱诳捎|及狀態的對象比做活在陽間的人,把不處于這個狀態的對象(無用對象)比做到了陰間的人。程序所能看見和使用的是陽間的人,假如閻王經常悄悄地讓幾個陰間的人復活,使他們在程序毫不知情的情況下溜回陽間,這只會擾亂程序的正常執行流程。

    11.4.5 比較finalize()方法和finally代碼塊

    在Object類中提供了finalize()方法,它的初衷是用于在對象被垃圾回收器回收之前,釋放所占用的相關資源,這和try…catch…finally語句的finally代碼塊的用途比較相似。但由于垃圾回收器是否會執行finalize()方法及何時執行該方法,都是不確定的,因此在程序中不能用finalize()方法來完成同時具有以下兩個特點的釋放資源的操作。

     必須執行。

    必須在某個確定的時刻執行。

    具有以上特點的操作更適合于放在finally代碼塊中。此外,可以在類中專門提供一個用于釋放資源的公共方法,最典型的就是java.io.InputStream和java.io.OutputStream類的close()方法,它們用于關閉輸入流或輸出流。當程序中使用了一個輸入流時,在結束使用前應該確保關閉輸入流。

    InputStream in;

    try{

    InputStream in=new FileInputStream("a.txt");

    }catch(IOException e){

    }finally{

    try{in.close();}catch(IOException e){…}

    }

    在多數情況下,應該避免使用finalize()方法,因為它會導致程序運行結果的不確定性。在某些情況下,finalize()方法可用來充當第二層安全保護網,當用戶忘記顯式釋放相關資源時,finalize()方法可以完成這一收尾工作。盡管finalize()方法不一定會被執行,但是有可能會釋放資源,這總比永遠不會釋放資源更安全。

    可以用自動洗衣機的關機功能來解釋finalize()方法的用途。自動洗衣機向用戶提供了專門的關機按鈕,這相當于AutoWasher類的close()方法,假如用戶忘記關機,相當于忘記調用AutoWasher對象的close()方法,那么自動洗衣機會在洗衣機停止工作后的1個小時內自動關機,這相當于調用finalize()方法。當然,這個例子不是太貼切,因為如果用戶忘記關機,洗衣機的自動關機操作總會被執行。

    posted on 2009-06-08 17:08 jimphei 閱讀(154) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲av中文无码| 国产精品深夜福利免费观看 | 77777午夜亚洲| 91精品免费国产高清在线| 亚洲国产高清视频| 8x8×在线永久免费视频| 亚洲AV无码成人精品区蜜桃| aa在线免费观看| 亚洲国产成人一区二区精品区| 免费看成人AA片无码视频吃奶| 亚洲精品无码mv在线观看网站| 在线观看免费视频一区| 亚洲成年轻人电影网站www| 久久久久国产免费| 亚洲乱码一二三四区国产| 毛片免费观看网址| 精品国产亚洲AV麻豆| 免费国产美女爽到喷出水来视频| 日韩在线一区二区三区免费视频| 在线播放亚洲第一字幕| 一级成人a毛片免费播放| 久久久久精品国产亚洲AV无码| 国内自产拍自a免费毛片| 日韩在线一区二区三区免费视频| 国产亚洲精品va在线| 亚洲电影免费观看| 亚洲s码欧洲m码吹潮| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 一级一黄在线观看视频免费| 久久99国产亚洲高清观看首页| 鲁大师在线影院免费观看| 亚洲国产精品成人综合久久久| 最新免费jlzzjlzz在线播放| 成年免费大片黄在线观看com| 久久青青成人亚洲精品| AV片在线观看免费| 一级毛片免费在线| 亚洲成年人免费网站| 丁香亚洲综合五月天婷婷| 久久久久久久99精品免费| 亚洲αⅴ无码乱码在线观看性色|