“序列化是将对象状态转换为可保持或可传输的格式的过程”。为什么要序列化,说的很清楚了,就是为了将对象状态进行持久化或者进行传输。注意这里说的是对象状态,所以只有对象的属性变量才会进行序列化,方法是不会序列化的。Java中所有实现Serializable接口的对象就表明是可序列化的。

 

示例代码:

import java.io.Serializable;

public class Person implements Serializable{
	
	private static final long serialVersionUID = -842029427676826563L;
	
	public static String name = "Tony";
	private int age;
	private transient int workDay = 5;
	private String fClub = "Arsenal";
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getWorkDay() {
		return workDay;
	}
	public void setWorkDay(int workDay) {
		this.workDay = workDay;
	}
	public String getfClub() {
		return fClub;
	}
	public void setfClub(String fClub) {
		this.fClub = fClub;
	}
}

 

 主测试类:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Hello {

	public static void main(String[] args) {
		Person person = new Person();
		person.setAge(26);
		person.setWorkDay(7);
		person.setfClub("Juventus");
		try {
			FileOutputStream fs = new FileOutputStream("foo.ser");
			ObjectOutputStream os = new ObjectOutputStream(fs);
			os.writeObject(person);
			os.close();

			Person.name = "Alex";

			FileInputStream in = new FileInputStream("foo.ser");
			ObjectInputStream s = new ObjectInputStream(in);
			Person p = (Person) s.readObject();
			System.out.println("name==" + Person.name + " age==" + p.getAge()
					+ " workDay==" + p.getWorkDay() + " fClub==" + p.getfClub());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

程序的输出结果为:



name==Alex age==26 workDay==0 fClub==Juventus



 

好了,下面一一解释上面代码的疑点:

1、serialVersionUID有什么用:(网络上的解释)

        如果你的类序列化存到硬盘上面后,可是后来你却更改了类的field(增加或减少或改名),当你Deserialize时,就会出现Exception的,这样就会造成不兼容性的问题。
       但当serialVersionUID相同时,它就会将不一样的field以type的预设值Deserialize,可避开不兼容性问题。       

       在Eclipse里写代码时,开始如果没加这个serialVersionUID就有警告提示。Eclipse提供两种生成方式:
一种是默认的1L,比如:private static final long serialVersionUID = 1L;
一种是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:private static final long serialVersionUID = xxxxL;

 

2、是不是所有的成员变量都会被序列化

        因为静态变量是属于类的,不是属于某个对象的,所以静态成员变量不会被序列化。序列化保存的是对象的状态,而静态变量属于类的状态,在序列化的时候不会被保存。所以上面程序的打印结果,name==Alex,而不是Tony,因为name根本没有被持久化到foo.ser文件中。 

        用关键字transient修饰的成员变量也不会被持久化。以前还真没接触过transient这个关键字,上网搜了一下对它的解释:“表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进去的。”

 

序列化保存的文件foo.ser文件里有什么内容,大概也能猜到:

1)对象的类型
2)对象属性的类型
3)对象属性的值

因为保存在文件里不是标准的文本内容,而是一些二进制内容,用Ultraedit以16进制格式打开,虽然有些显示为了乱码,但是大概能看到的也是上面的3个内容。

 

值得一提的是,当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化,所以当然引用的对象也要是可序列化的。

 

有关序列化的有用参考文章:

http://www.blogjava.net/jiangshachina/archive/2012/02/13/369898.html

http://www.ibm.com/developerworks/cn/java/j-5things1/

http://regedit-123.iteye.com/blog/1109191