1. 程式人生 > >JAVA程式設計思想(第4版)物件終結條件,system.gc(),finalize()一部分用法小結

JAVA程式設計思想(第4版)物件終結條件,system.gc(),finalize()一部分用法小結

finalize()有一個有趣的用法,它並不依賴於每次都要對finalize()進行呼叫,這就是物件終結條件的驗證。

當對某個物件不再感興趣----也就是它可以被清理了,這個物件應該處於某種狀態,使它佔用的記憶體可以被安全地釋放。

例如,要是物件代表了一個開啟的檔案,在物件被回收前程式設計師應該關閉這個檔案。只要物件中存在沒有被適當清理的

部分,程式就存在很隱晦的缺陷。finalize()可以用來最終發現這種情況----儘管它並不總是被呼叫。如果某次finalize()

動作使得缺陷被發現,那麼就可以找出問題所在 ,這才是人們真正關心的。

舉個例子:

package test;

public class Tank {
	boolean status=false;//false為空,true為滿
	
	Tank(boolean stat){
		status=stat;
	}
	
	void empty(){
		status=false;
	}
	
	protected void finalize(){
		if(status)
			System.out.println("error");	
	}
}
package test;


public class Test {
	public static void main(String args[]){
		Tank tk1=new Tank(true);
		
		tk1.empty();
		
		//Tank tk2=new Tank(true);
		new Tank(true);	//物件一建立就成為垃圾,因為沒有引用指向它	
		
		System.gc();
	}
}
程式執行結果如圖:

本例的終結條件是:所有的Tank物件在被當做垃圾回收前都應該置為空,但是在main方法中,由於程式設計師的錯誤,有一個tank被置為滿。

要是沒有finalize()來驗證終結條件,將很難發現這種缺陷。

注意,System.gc()用於強制進行終結動作即垃圾回收動作。而如果不強制這麼做,假設在之後的程式中由於分配大量的儲存空間而導致垃圾回收動作

執行,也能找到錯誤的Tank物件,即執行finalize()方法。

而需要注意的一點是在上面原始碼中我註釋了Tank tk2=new Tank(true);假如不把它註釋,而是把new Tank(true);註釋會出現怎麼樣的情況呢?即原始碼如下:

package test;


public class Test {
	public static void main(String args[]){
		Tank tk1=new Tank(true);
		
		tk1.empty();
		
		Tank tk2=new Tank(true);
		//new Tank(true);		
		
		System.gc();
	}
}

程式執行結果如圖:


不會執行finalize()方法,即不會列印錯誤資訊。這是為什麼呢?

是由於System.gc()的執行機制有關,準確來說是java的垃圾回收機制有關。

第一種情況new Tank(true);只是建立一個物件,並沒有引用指向它,所以該物件的引用計數為0,即這個物件一創建出來就成為垃圾,所以呼叫System.gc()會執行回收動作。

而第二種情況Tank tk2=new   Tank(true);是建立一個物件,並且讓tk2指向該物件,所以該物件的引用計數為1,即還有引用指向該物件,所以不需要被回收,呼叫System.gc()並不會執行回收動作,因為沒有垃圾,所以程式結果自然為沒有列印任何東西。

最後是System.gc()方法的原始碼解釋:

Runs the garbage collector.

Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

即呼叫垃圾回收器。呼叫gc方法表明Java虛擬機器盡最大努力去回收未使用的物件從而使目前可用的記憶體得到快速重複利用。當控制器執行這個方法呼叫時,java虛擬機器盡最大努力去回收廢棄物件的空間。