java 正确使用序列化(7)
发布时间:2021-06-06
发布时间:2021-06-06
this.firstName = firstName;
}
public String toString()
{
return "Person " + firstName + " " + lastName;
}
}
修改后的Person为:
/**
* 修改后的Person类,我们将firstName和lastName变成了fullName
*/
import java.io.*;
public class Person extends Humanoid
implements java.io.Serializable
{
private String fullName;
private static final long serialVersionUID =6921661392987334380L;
private Person()
{
}
public Person(String fullName)
{
stName = fullName;
}
public String toString()
{
return "Person " + fullName;
}
}
为此,我们需要编写Person类的readObject方法如下:
private void readObject(ObjectInputStream ois)
throws IOException,ClassNotFoundException
{
ObjectInputStream.GetField gf = ois.readFields();
fullName = (String) gf.get("fullName", null);
if (fullName == null)
{
String lastName = (String) gf.get("lastName", null);
如何正确的使用Java序列化技术 技术研究系列
String firstName = (String) gf.get("firstName", null);
if ( (lastName == null) || (firstName == null))
{
throw new InvalidClassException("invalid Person");
}
fullName = firstName + " " + lastName;
}
}
我们的执行顺序是:
1) 编译老的Person及所有类;
2) 将老的Person序列化到文件里;
3) 修改为新版本的Person类;
4) 编译新的Person类;
5) 反序列化Person;
执行结果非常顺利,修改后的反序列化机制仍然正确的从流中获取了旧版本Person 的
属性信息并完成对新版本的Person的属性赋值。
使用ObjectInputStream的readObject 来处理反序列化的属性时,有两点需要注意:
u 一旦采用自己控制属性的反序列化,则必须完成所有属性的反序列化(即要给所有
属性赋值);
u 在使用内部类GetField 的get 方法的时候需要注意,如果get 的是一个既不在老版
本出现的属性,有没有在新版本出现的属性,则该方法会抛出异常:
IllegalArgumentException: no such field,所以我们应该在一个try块里
来使用该方法。
同理,我们可以通过writeObject 方法来控制对象属性的序列化过程。这里就不再一一
举例了,如果你有兴趣的话,可以自己实现Person 类的writeObject 方法,并且使用
ObjectOutputStream的内部类PutField来完成属性的手动序列化操作。
3 总结
Java 序列化机制提供了强大的处理能力。一般来讲,为了尽量利用Java 提供的自动化
机制,我们不需要对序列化的过程做任何的干扰。但是在某些时候我们需要实现一些特殊的
功能,比如类的多版本的控制,特殊字段的序列化控制等。我们可以通过多种
方式来实现这
些功能:
u 利用序列化机制提供的钩子函数readObject和writeObject;
u 覆盖序列化类的metaData 信息;
如何正确的使用Java序列化技术 技术研究系列
u 使类实现Externalizable 接口而不是实现Serializable接
下一篇:营龙煤业基本情况