中恢复Person 这个对象,
我们需要借助如下的类:
java.io.ObjectInputStream
从文件里把Person类反序列化的代码实现如下:
/**
* Person的反序列化类,通过该类从文件系统中读出序列化的数据,并构造一个
* Person对象。
*/
import java.io.*;
public class ReadInstance
{
public static void main(String [] args) throws Exception
{
if (args.length != 1)
{
System.out.println("usage: java ReadInstance filename");
System.exit(-1);
}
FileInputStream fis = new FileInputStream(args[0]);
ObjectInputStream ois = new ObjectInputStream(fis);
Object o = ois.readObject();
如何正确的使用Java序列化技术 技术研究系列
System.out.println("read object " + o);
}
}
1.3 序列化对类的处理原则
并不是一个实现了序列化接口的类的所有字段及属性都是可以序列化的。我们分为以下
几个部分来说明:
u 如果该类有父类,则分两种情况来考虑,如果该父类已经实现了可序列化接口。则
其父类的相应字段及属性的处理和该类相同;如果该类的父类没有实现可序列化接
口,则该类的父类所有的字段属性将不会序列化。
u 如果该类的某个属性标识为static类型的,则该属性不能序列化;
u 如果该类的某个属性采用transient关键字标识,则该属性不能序列化;
需要注意的是,在我们标注一个类可以序列化的时候,其以下属性应该设置为transient
来避免序列化:
u 线程相关的属性;
u 需要访问IO、本地资源、网络资源等的属性;
u 没有实现可序列化接口的属性;(注:如果一个属性没有实现可序列化,而我们又
没有将其用transient 标识, 则在对象序列化的时候, 会抛出
java.io.NotSerializableException 异常)。
1.4 构造函数和序列化
对于父类的处理,如果父类没有实现序列化接口,则其必须有默认的构造函数(即没有
参数的构造函数)。为什么要这样规定呢?我们来看实际的例子。仍然采用上面的Humanoid
和Person 类。我们在其构造函数里分别加上输出语句:
/**
* 抽象基本类,完成一些基本的定义
*/
public abstract class Humanoid
{
protected int noOfHeads;
private static int totalHeads;
public Humanoid()
{
this(1);
System.out.println("Human's default constructor is invoked");
}
public Humanoid(int noOfHeads)
{
if (noOfHeads > 10)
throw new Error("Be serious. More than 10 heads?!");
如何正确的使用Java序列化技术 技术研究系列
this.noOfHeads = noOfHeads;
synchronized (Humanoid.class)
{
totalHeads += noOfHeads;
}
}
public int getHeadCount()
{
return totalHeads;
}
}
/**
* Humanoid的实现类,实现了序列化接口
*/
import java.io.*;
public cl
ass Person extends Humanoid
implements java.io.Serializable
{
private String lastName;
private String firstName;
private transient Thread w