一、串行化的概念和目的
1.什么是串行化
对象的寿命通常随着生成该对象的程序的终止而终止。有时候,可能需要将对象的状态保存下来,在需要时再将对象恢复。我们把对象的这种能记录自己的状态以便将来再生的能力。叫作对象的持续性(persistence)。对象通过写出描述自己状态的数值来记录自己 ,这个过程叫对象的串行化(Serialization) 。串行化的主要任务是写出对象实例变量的数值。如果交量是另一对象的引用,则引用的对象也要串行化。这个过程是递归的,串行化可能要涉及一个复杂树结构的单行化,包括原有对象、对象的对象、对象的对象的对象等等。对象所有权的层次结构称为图表(graph)。
2.串行化的目的
Java对象的单行化的目标是为Java的运行环境提供一组特性,如下所示:
1) 尽量保持对象串行化的简单扼要 ,但要提供一种途径使其可根据开发者的要求进行扩展或定制。
2) 串行化机制应严格遵守Java的对象模型 。对象的串行化状态中应该存有所有的关于种类的安全特性的信息。
3) 对象的串行化机制应支持Java的对象持续性。
4) 对象的串行化机制应有足够的 可扩展能力以支持对象的远程方法调用(RMI)。
5) 对象串行化应允许对象定义自身 的格式即其自身的数据流表示形式,可外部化接口来完成这项功能。
二、串行化方法
从JDK1.1开始,Java语言提供了对象串行化机制 ,在java.io包中,接口Serialization用来作为实现对象串行化的工具 ,只有实现了Serialization的类的对象才可以被串行化。
Serializable接口中没有任何的方法。当一个类声明要实现Serializable接口时,只是表明该类参加串行化协议,而不需要实现任何特殊的方法。下面我们通过实例介绍如何对对象进行串行化。 (转自http://blog.csdn.net/sodino/archive/2008/12/21/3576147.aspx)
关于对象序列化和反序列化的顺序:反序列化是按照序列化的顺序进行读取的,所以反序列化的时候一定要按照序列化的顺序读取
自己写的列子
package twelve;
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.util.Date;
import java.util.GregorianCalendar;
/**
* @Title ObjectFileTest.java
* @description TODO
* @author qinpeng
* @date Aug 19, 2009 10:40:49 PM
*/
public class ObjectFileTest {
public static void main(String[] args) {
ObjectOutputStream out = null;
ObjectInputStream in = null;
Manager boss = new Manager("carl c", 8000, 1987, 12, 15);
boss.setBonus(5000);
Employee[] staff = new Employee[3];
staff[0] = boss;
staff[1] = new Employee("harry", 5000, 1985, 8, 21);
staff[2] = new Employee("tony", 4000, 1986, 6, 12);
try {
try {
out = new ObjectOutputStream(new FileOutputStream(
"employee.dat"));
out.writeObject(staff);
} finally {
if (out != null) {
out.close();
}
}
} catch (FileNotFoundException foundE) {
foundE.printStackTrace();
System.err.print("employee.dat is not found");
} catch (IOException ioE) {
ioE.printStackTrace();
System.err.print("IOException of main");
}
try {
try {
in = new ObjectInputStream(new FileInputStream("employee.dat"));
Employee[] newStaff = (Employee[]) in.readObject();
for (Employee e : newStaff) {
System.out.println(e);
}
} finally {
if (in != null) {
in.close();
}
}
} catch (ClassNotFoundException classE) {
classE.printStackTrace();
System.err.print("employee.dat is not found");
} catch (FileNotFoundException foundE) {
foundE.printStackTrace();
System.err.print("employee.dat is not found");
} catch (IOException ioE) {
ioE.printStackTrace();
System.err.print("IOException of main");
}
}
}
class Employee implements Serializable {
private String name;
//private transient String name;
private double salary;
private Date hireDay;
public Employee() {
}
public Employee(String n, double s, int year, int month, int day) {
name = n;
salary = s;
GregorianCalendar claendar = new GregorianCalendar(year, month - 1, day);
}
public void raiseSalary(double byPercent) {
double raise = salary * byPercent / 100;
salary += raise;
}
public String toString() {
return getClass().getName() + "name=" + name + "---salary=" + salary
+ "---hirDay=" + hireDay;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Date getHireDay() {
return hireDay;
}
public void setHireDay(Date hireDay) {
this.hireDay = hireDay;
}
}
class Manager extends Employee {
private double bonus;
public Manager(String n, double s, int year, int month, int day) {
super(n, s, year, month, day);
}
public String toString() {
return super.toString() + "bonus=" + bonus;
}
public double getSalary() {
double baseSalay = super.getSalary();
return baseSalay + bonus;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
}
这里当域没有用 transient 修饰的时候,该域作为对象的内容被保存起来。输出结果如下:
twelve.Managername=carl c---salary=8000.0bonus=5000.0
twelve.Employeename=harry---salary=5000.0
twelve.Employeename=tony---salary=4000.0
如果域 name 使用 transient 该域将不会进行保存
class Employee implements Serializable {
//private String name;
private transient String name;
private double salary;
private Date hireDay;
........
结果如下:
twelve.Managername=null---salary=8000.0bonus=5000.0
twelve.Employeename=null---salary=5000.0
twelve.Employeename=null---salary=4000.0