如果你使用过Java中的序列化,你会注意到的第一件事情是它是多么的容易编码。你会注意到的第二样事情是通过改变你的类打破序列化是多么的容易。
当你序列化一个对象时,类元信息与对象的状态一起序列化。其中被写入的一块元数据是类的序列版本。当你试图从序列化的数据中重新创建对象时,如果当前的类的版本与序列化的数据中的版本号不匹配,就会抛出一个InvalidClassException异常。
你可以通过自己处理类的版本来防止出现这个错误。要为你的类提供一个版本号,定义一个表态final long型的类成员,名为serialVersionUID。在编译你的类的时候,这个成员的值将用于标识你的类的版本。
如果你正试图使用从一个没有加版本的类序列来的数据的话,你可以使用serialver命令行工具从老类中提取版本号。如果你然后使用这个版本号编译你的新类,你就能够使用新类反序列化老数据。
在你自己负责类的版本的时候需要小心。如果类在新一个版本被序列化之后已经加入了新的属性,那么这些值在反序列化的时候将不会被初始化而且也不会有错误抛出。如果在序列化之后有属性被删除,那么在从序列化的数据中实例化的时候这些属性的数据将会被忽略。
在任何一种情况下都没有错误抛出,但是你不知道一些属性没有被初始化或者有数据被丢弃。正如你看到的,为自己的Java类提供版本控制很简单也很方便,但是也有风险。
下面是一个简单的具有程序员提供的版本控制的类以及serialver的输出:
// 代码
import java.io.Serializable;
public class Zed implements Serializable {
private double value;
private static final long serialVersionUID = 4;
public double getValue() {
return this.value;
}
public void setValue(double value) {
this.value = value;
}
}
命令和输出
>serialver Zed
Zed: static final long serialVersionUID =
4L;