序列化和反序列化(二)——Serializable 接口

Serializable 接口:該接口沒有方法或字段,僅用於標識由該接口實現類創建的對象是可序列化的。

       示例:

import java.io.Serializable;

public class UserInfo implements Serializable {

	private static final long serialVersionUID = -564040236692883153L;
	private int age;
	private String name;

	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "name='" + name + '\'' + ", age=" + age;
	}
}
import java.io.*;

public class Test {
	
	/**
	 * 序列化
	 * 
	 * @author GaoHuanjie
	 */
	public static void serialize(){
		UserInfo userInfo = new UserInfo();
		userInfo.setAge(23);
		userInfo.setName("Tom");
		System.out.println(userInfo);
		ObjectOutput objectOutput = null;
		try {
			objectOutput = new ObjectOutputStream(new FileOutputStream("D:\\user_info.ser"));
			objectOutput.writeObject(userInfo);
			objectOutput.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (objectOutput!=null) {
				try {
					objectOutput.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 反序列化
	 * 
	 * @author GaoHuanjie
	 */
	public static void deserialize(){
		ObjectInput objectInput = null;
		try {
			objectInput = new ObjectInputStream(new FileInputStream("D:\\user_info.ser"));
			UserInfo userInfo = (UserInfo) objectInput.readObject();
			System.out.println(userInfo);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (objectInput!=null) {
				try {
					objectInput.close();
				} catch (IOException e) {
					e.printStackTrace();
				} 
			}
		}
	}

	public static void main(String[] args) {
		serialize();//序列化
		deserialize();//反序列化
	}
}

serialVersionUID常量

       實現Serializable接口的類須顯式聲明serialVersionUID常量,該常量作用如下:反序列化能否成功取決於三方面,首先序列化和反序列化類所在包相同,其次序列化和反序列化類的類名相同,最後序列化和反序列化類serialVersionUID的值要相同,兩個類中的代碼可以不同,如果不指定serialVersionUID,則類出現警告,但這是次要的,更重要的是序列化時將根據JavaTM)對象序列化規範爲該類計算一個默認的serialVersionUID值,這就要求反序列化時使用的類與序列化時使用的類必須完全相同(有相同的屬性和方法),否則反序列化失敗,因爲反序列化時serialVersionUID的值也是根據JavaTM)對象序列化規範計算出來的默認值,由於序列化類代碼和反序列化類代碼不同,則serialVersionUID的值肯定不同;但在實際開發中序列化類代碼和反序列化類代碼極有可能不同,在這種情況下爲了反序列化成功就要求顯式聲明serialVersionUID常量且值要相同。serialVersionUID的生成策略有兩種:一個是固定的 1L,一個是根據JavaTM)對象序列化規範生成的 long 類型數據;如果沒有特殊需求,推薦使用固定值,這樣便於序列化類代碼和反序列化類serialVersionUID一致;如果限制某些用戶的使用,則推薦第二種生成策略。

transient 關鍵字

       在序列化時,transient 關鍵字修飾的成員變量不會被序列化;在反序列化時,transient 關鍵字修飾的成員變量被賦以默認值,如整型爲0,浮點型爲0.0,引用類型爲null

static關鍵字

       在序列化時,static關鍵字修飾的成員變量不會被序列化。序列化保存的是對象的狀態,靜態變量屬於類的狀態,因此序列化並不保存靜態變量,即序列化信息中不包含這個靜態成員域。

import java.io.Serializable;

public class UserInfo implements Serializable {

	private static final long serialVersionUID = 1L;
	private static int count;
	public UserInfo() {
		count++;
	}
	public String toString() {
		return "count:" + count;
	}
}

       static修飾的成員變量,序列化和反序列化代碼在一個進程中執行時會序列化成功,因爲序列化時jvm已經把靜態變量加載進來了,所以反序列化時獲取的是加載好的靜態變量,如下例子:

import java.io.*;

public class Test {

	public static void main(String[] args) {
		try {
			ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream("user_info.ser"));
			objectOutput.writeObject(new UserInfo());
			objectOutput.close();

			ObjectInput objectInput = new ObjectInputStream(new FileInputStream("user_info.ser"));
			UserInfo userInfo = (UserInfo) objectInput.readObject();
			System.out.println(userInfo);
			objectInput.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

       static修飾的成員變量,序列化和反序列化代碼不再一個進程,由於反序列化時是重新加載靜態變量,所以靜態變量是初始值,如下列子:

序列化:

import java.io.*;

public class Test1 {

	public static void main(String[] args) {
		try {
			ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream("user_info.ser"));
			objectOutput.writeObject(new UserInfo());
			objectOutput.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

反序列化:
import java.io.*;

public class Test2 {

	public static void main(String[] args) {
		try {
			ObjectInput objectInput = new ObjectInputStream(new FileInputStream("user_info.ser"));
			UserInfo userInfo = (UserInfo) objectInput.readObject();
			System.out.println(userInfo);
			objectInput.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章