java物件序列化

小弟季義欽發表於2012-10-31
/**
 * 
 */
package iostream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * 
 * 物件的序列化(Serializable):
 * 
 * 當你建立物件的時候,只要你需要它,它就會一直存在。但是當程式終止的時候,無論如何都不會在繼續存在。
 * 儘管這麼做是有意義的,但是我們仍然希望有時候呢能夠在程式不執行的情況下仍然能夠儲存物件資訊。
 *
 * 物件序列化的概念加入到Java語言中有兩個原因:
 * 1 Java的遠端方法呼叫(RMI),它使得存活在其他計算機上面的物件看起來像是
 * 存活於本機上一樣;
 * 2 對於Java Bean來說,物件的序列化是必須的,使用一個Bean時,一般是在
 * 設計階段對它的狀態資訊進行配置,然後將這種狀態資訊儲存下來,在程式啟動
 * 的時候恢復。
 */

/**
 * 只需要實現Serializable介面(僅是一個標記介面,不包含
 * 任何方法),物件的序列化處理就會非常簡單。
 * */
class Color implements Serializable{
	String name;
	public Color(String name, int r, int g, int b){
		System.out.print("Color Constructor\n");
		this.name = name;
		this.r = r;
		this.g = g;
		this.b = b;
	}
	int r;
	int g;
	int b;
}

/**
 * 儲存Orange的時候不僅僅是指儲存該物件的“全景圖”,而是會
 * 追蹤該物件中包含的所有引用,並儲存那些物件。
 * */
class Orange implements Serializable{
	private String from;			//即使是private,也會被序列化
	private static int size = 0;	//不是說static域不能被序列化麼,為什麼這裡被序列化了???
	transient int weight;			//要想不被序列化,就標記成transient
	private Color color;			//包含一個Color物件
	public Orange(String from, int size, int weight, Color color){
		System.out.print("Orange Constructor\n");
		this.from = from;
		this.size = size;
		this.color = color;
		this.weight = weight;
	}
	
	public int getSize(){
		return size;
	}
	public String toString(){
		return "Color: "+color.name+","+color.r+","+color.g+"," +
				""+color.b+", From: "+from+", Weight: "+weight+", Size: "+size;
	}
}

/**
 * 測試物件的序列化
 * */
public class ObjectSerializationTest {

	/**
	 * 儲存一個Orange物件到檔案
	 * */
	public void testStoreObject(String file) throws IOException{
		Orange o = new Orange("NanJing", 10, 20, new Color("green", 11,130,77));
		System.out.println("Before serialize:"+o);
		
		//新建一個檔案
		File f = new File(file);
		f.createNewFile();
		f.deleteOnExit();
		
		//使用過濾器ObjectOutputStream將物件存入檔案
		ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file));
		os.writeObject(o);
		os.close();		
	}
	
	
	/**
	 * 注意
	 * (1) 如果這個恢復物件的程式碼寫在另外一個路徑下,而這個路徑下面找不到Orange類,
	 * 即Orange.class檔案不在這個路徑下(Orange.class在iostream下)。那麼恢復這個物件
	 * 的時候會發生ClassNotFoundException。因為開啟和讀取儲存的Orange物件中的內容
	 * 的時候需要用到Orange.class檔案中的類資訊。
	 * (2) 恢復Orange物件的時候,其構造器不會被呼叫。這個過程是通過從InputStream中
	 * 取得資料完成的。同時需要根據class檔案才能完成。
	 * */
	public void testReadObject(String file) throws FileNotFoundException, IOException, ClassNotFoundException, IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException{
		//通過過濾器ObjectInputStream從檔案流輸入流中讀取一個物件
		ObjectInputStream oi = new ObjectInputStream(new FileInputStream(file));
		Orange o = (Orange)oi.readObject();
		oi.close();
		System.out.println("After serialize"+o);
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		ObjectSerializationTest ost = new ObjectSerializationTest();
		String storeFile = "./testDir/object.txt";
		String restoreFile = "./testDir/object.txt";
		
		System.out.print("\n-------------- 向檔案中存入一個物件 --------------\n");
		ost.testStoreObject(storeFile);	
		
		System.out.print("\n-------------- 從檔案中恢復一個物件 --------------\n");
		ost.testReadObject(restoreFile);
	}
}

相關文章