天天看點

第七條 避免使用終結方法

一、finalize的作用

       由于在java中存在垃圾回收器,是以許多人認為它相當于C++中的析構函數,然而,垃圾回收器隻會回收使用new方法獲得的記憶體,而通過其他方法得到的記憶體以及任何其他系統資源(比如檔案句柄、資料庫連接配接等)都不能通過垃圾回收器得到釋放。是以我們需要其它的釋放函數。那麼能夠做到這一切的是finalize()方法(但是,一定不要使用finalzie方法去釋放這些資源)。finalize方法的工作原理“假定”是這樣的:一旦垃圾回收器準備好釋放對象占用的存儲空間,将首先調用finalize()方法,并在下一次垃圾回收動作發生時,才會真正回收對象占用的記憶體。是以,如果有一些需要釋放的資源,可以講釋放語句寫在finalize方法中,它們将在垃圾回收器工作時自動得到執行。那麼,為什麼不能使用該方法去釋放資源呢?

二、為什麼盡量避免使用finalize函數

     首先,finalize一定會被執行,但是并不總是那麼及時,原因有二:

          1、垃圾回收器并不總是工作,隻有當記憶體資源告急時,垃圾回收器才會工作;

          2、即使垃圾回收器工作,finalize方法也不一定得到執行,這是由于程式中的其他線程的優先級遠遠高于執行finalize()函數線程的優先級。

          是以,當finalize還沒有被執行時,系統的其他資源,比如檔案句柄、資料庫連接配接池等已經消耗殆盡,造成系統崩潰。

     第二,如果一種未被捕獲的異常在使用finalize方法時被抛出,這個異常不會被捕獲,finalize方法的終結過程也會終止,造成對象出于破壞的狀态。

     第三,垃圾回收和finalize方法的執行本身就是對系統資源的消耗,有可能造成程式的暫時停止,是以在程式中盡量避免使用finalize方法。

三、finalize函數的應用場景

       1、當對象的使用者忘記顯示釋放使用資源的時候,finalize函數充當安全網的角色,相當于最後一道防火牆(祈禱finalize方法能夠被及時執行);

       2、釋放本地方法申請的非關鍵資源(程式中嵌入的其他語言申請的非關鍵資源,關鍵資源仍然要顯示釋放);

       3、記得在重載的finalize方法中最後調用super.finalize();系統不會自動調用

四、為什麼不能顯示直接調用finalize方法

      如前文所述,finalize方法在垃圾回收時一定會被執行,而如果在此之前顯示執行的話,也就是說finalize會被執行兩次以上,而在第一次資源已經被釋放,那麼在第二次釋放資源時系統一定會報錯,是以一般finalize方法的通路權限和父類保持一緻,為protected。

繼續閱讀