5.5 清理:終結(jié)處理和垃圾回收
Java中使用垃圾回收器負責(zé)回收無用對象占據(jù)的內(nèi)存資源涩拙。但是有特殊情況,假定你的對象(并非使用new創(chuàng)建)獲得了一塊特殊的內(nèi)存區(qū)域酿秸,由于垃圾回收器只知道回收那些經(jīng)由new分配的內(nèi)存澳叉,所以它不知道該如何釋放該對象的這塊特殊內(nèi)存紊遵。為了應(yīng)對這種情況污抬,Java允許類定義一個名為finalize()的方法汞贸,一旦垃圾回收器準備好釋放該對象占用的存儲空間,將首先調(diào)用其finalize()方法,并在下一次垃圾回收動作真正發(fā)生時才會真正回收對象占用的內(nèi)存矢腻。所以定義finalize()方法门驾,能在垃圾回收時刻做一些重要的清理工作。
之所以要有finalize()踏堡,是由于在分配內(nèi)存時可能使用了類似C語言中的做法猎唁,例如在非Java代碼中調(diào)用了C的malloc()函數(shù)系列來分配存儲空間,而且除非調(diào)用了free()函數(shù)否則存儲空間將無法得到釋放顷蟆,從而造成內(nèi)存泄漏。當(dāng)然腐魂,free()是C語言中的函數(shù)帐偎,所以需要在finalize()中使用本地方法調(diào)用。
如果希望進行處了釋放存儲空間之外的清理工作蛔屹,還是得明確調(diào)用某個恰當(dāng)?shù)姆椒ǎǘ^不能直接調(diào)用finalize方法)削樊。因為無論是垃圾回收還是終結(jié)方法,都不保證一定會發(fā)生兔毒。如果Java虛擬機并未面臨內(nèi)存耗盡的情形漫贞,它是不會浪費時間去執(zhí)行垃圾回收已恢復(fù)內(nèi)存的。
finalize()還有一個用法育叁,那就是對象終結(jié)條件的驗證迅脐。如果某個對象在被回收時必須處于某種特定的狀態(tài),那么可以在終結(jié)方法中進行驗證豪嗽。
垃圾回收器如何工作(P90-91):(1)垃圾回收器對于提高對象的創(chuàng)建速度谴蔑,具有明顯的效果。
(2)Java虛擬機的堆實現(xiàn)更像一個傳送帶龟梦,每分配一個新對象隐锭,它就往前移動一格。這意味著對象存儲空間的分配速度非臣品。快钦睡。Java的堆指針只是簡單的移動到尚未分配的區(qū)域,其效率了比得上C++在堆棧上的分配空間的效率躁倒。
(3)垃圾回收器工作時荞怒,將一面回收空間,一面使堆中的對象緊湊排列樱溉,這樣堆指針就可以很容易的移動到更靠近傳送帶的開始處挣输,也就盡量避免了頁面錯誤。通過垃圾回收器對對象重排列福贞,實現(xiàn)了一種高速的撩嚼,有無限空間可分配的堆模型。
(4)Java虛擬機中有許多附加技術(shù)用意提升速度,尤其是與加載器操作有關(guān)的完丽,被稱為(Just-In-Time恋技,JIT)編譯器的技術(shù)。這種技術(shù)把程序全部或部分翻譯成本地機器碼(將字節(jié)碼編譯成本地機器碼)逻族,程序運行速度因此得到提升蜻底。
5.7 初始化
(1)可以使用構(gòu)造器進行初始化,但是無法阻止自動初始化的進行聘鳞,它將在構(gòu)造器被調(diào)用之前發(fā)生薄辅。
public class Counter{
? ? ?int i;
? ? ?public Counter(){
? ? ? ? ?i=7;
? ? }
}
那么i首先會被置為0抠璃,然后變成7站楚。
(2)在類的內(nèi)部,成員變量會在任何方法(包括構(gòu)造器)被調(diào)用之前得到初始化搏嗡。
總結(jié)一下對象的創(chuàng)建過程窿春,假設(shè)有一個名為Dog的類:
(1)構(gòu)造器實際上是靜態(tài)方法,當(dāng)首次創(chuàng)建Dog對象或者Dog類的靜態(tài)方法/靜態(tài)域被首次訪問時采盒,Java解釋器查找類路徑旧乞,以定位Dog.class文件。
(2)載入Dog.class(創(chuàng)建一個Class對象)磅氨,執(zhí)行靜態(tài)初始化的所有動作尺栖。因此,靜態(tài)初始化只在Class對象首次加載的時候進行一次悍赢。
(3)當(dāng)用new Dog() 創(chuàng)建對象是决瞳,首先在堆上分配存儲空間,這塊存儲空間會被清零(成員變量設(shè)為默認值)左权。
(4)執(zhí)行所有字段定義處的初始化動作皮胡。
(5)執(zhí)行構(gòu)造器。
5.9 枚舉類型
當(dāng)你創(chuàng)建enum時赏迟,編譯器會自動創(chuàng)建toString方法屡贺,static values()方法,返回按照聲明順序構(gòu)成的enum數(shù)組锌杀,ordinal()方法返回一個枚舉值在enum中的聲明位置甩栈。
for (Color c:Color.values()){
System.out.println(c+",ordinal:"+c.ordinal());
}