5.5 清理:終結處理和垃圾回收
Java中使用垃圾回收器負責回收無用對象占據的內存資源。但是有特殊情況,假定你的對象(并非使用new創建)獲得了一塊特殊的內存區域,由于垃圾回收器只知道回收那些經由new分配的內存,所以它不知道該如何釋放該對象的這塊特殊內存。為了應對這種情況,Java允許類定義一個名為finalize()的方法,一旦垃圾回收器準備好釋放該對象占用的存儲空間,將首先調用其finalize()方法,并在下一次垃圾回收動作真正發生時才會真正回收對象占用的內存。所以定義finalize()方法,能在垃圾回收時刻做一些重要的清理工作。
之所以要有finalize(),是由于在分配內存時可能使用了類似C語言中的做法,例如在非Java代碼中調用了C的malloc()函數系列來分配存儲空間,而且除非調用了free()函數否則存儲空間將無法得到釋放,從而造成內存泄漏。當然,free()是C語言中的函數,所以需要在finalize()中使用本地方法調用。
如果希望進行處了釋放存儲空間之外的清理工作,還是得明確調用某個恰當的方法(而絕不能直接調用finalize方法)。因為無論是垃圾回收還是終結方法,都不保證一定會發生。如果Java虛擬機并未面臨內存耗盡的情形,它是不會浪費時間去執行垃圾回收已恢復內存的。
finalize()還有一個用法,那就是對象終結條件的驗證。如果某個對象在被回收時必須處于某種特定的狀態,那么可以在終結方法中進行驗證。
垃圾回收器如何工作(P90-91):(1)垃圾回收器對于提高對象的創建速度,具有明顯的效果。
(2)Java虛擬機的堆實現更像一個傳送帶,每分配一個新對象,它就往前移動一格。這意味著對象存儲空間的分配速度非常快。Java的堆指針只是簡單的移動到尚未分配的區域,其效率了比得上C++在堆棧上的分配空間的效率。
(3)垃圾回收器工作時,將一面回收空間,一面使堆中的對象緊湊排列,這樣堆指針就可以很容易的移動到更靠近傳送帶的開始處,也就盡量避免了頁面錯誤。通過垃圾回收器對對象重排列,實現了一種高速的,有無限空間可分配的堆模型。
(4)Java虛擬機中有許多附加技術用意提升速度,尤其是與加載器操作有關的,被稱為(Just-In-Time,JIT)編譯器的技術。這種技術把程序全部或部分翻譯成本地機器碼(將字節碼編譯成本地機器碼),程序運行速度因此得到提升。
5.7 初始化
(1)可以使用構造器進行初始化,但是無法阻止自動初始化的進行,它將在構造器被調用之前發生。
public class Counter{
? ? ?int i;
? ? ?public Counter(){
? ? ? ? ?i=7;
? ? }
}
那么i首先會被置為0,然后變成7。
(2)在類的內部,成員變量會在任何方法(包括構造器)被調用之前得到初始化。
總結一下對象的創建過程,假設有一個名為Dog的類:
(1)構造器實際上是靜態方法,當首次創建Dog對象或者Dog類的靜態方法/靜態域被首次訪問時,Java解釋器查找類路徑,以定位Dog.class文件。
(2)載入Dog.class(創建一個Class對象),執行靜態初始化的所有動作。因此,靜態初始化只在Class對象首次加載的時候進行一次。
(3)當用new Dog() 創建對象是,首先在堆上分配存儲空間,這塊存儲空間會被清零(成員變量設為默認值)。
(4)執行所有字段定義處的初始化動作。
(5)執行構造器。
5.9 枚舉類型
當你創建enum時,編譯器會自動創建toString方法,static values()方法,返回按照聲明順序構成的enum數組,ordinal()方法返回一個枚舉值在enum中的聲明位置。
for (Color c:Color.values()){
System.out.println(c+",ordinal:"+c.ordinal());
}