我从概念上理解Java序列化,但是我对可序列化对象的版本兼容性感到非常困惑。当引用“版本”时,它是否意味着:
是两个层次关系的类,其中一个是属性的加/减?
或两个类符合不同的编译版本?
或两者兼而有之?
我的理解是我们必须保持suid一致,JVM会检查版本兼容性。
结果我设计了一个试验测试java序列化版本不兼容性的实验,代码片段如下,其中我使suid不同:
public static class Incompatible implements Serializable {
private static final long serialVersionUID = 1L;
private int i;
public Incompatible(int i){
this.i = i;
}
public int getI(){
return i;
}
}
public static class IncompFoo extends Incompatible {
private static final long serialVersionUID = 2L;
public IncompFoo(int i){
super(i);
}
}
@Test
public void incompatibleTest() throws IOException, ClassNotFoundException{
FileOutputStream fos = new FileOutputStream(new File("foo.ser"));
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(new IncompFoo(10));
oos.close();
FileInputStream fis = new FileInputStream(new File("foo.ser"));
ObjectInputStream ois = new ObjectInputStream(fis);
Incompatible foo = (Incompatible)ois.readObject();
ois.close();
Assert.assertEquals(10, foo.getI());
}
我预计会出现InvalidClassException,因为这两个类有不同的suid。令我惊讶的是,测试完成了。
哪一部分错了?我们有一个简单的方法来创建InvalidClassException吗?
答案 0 :(得分:1)
您的示例编写一个对象,读取它并将其强制转换为超类。没有什么有趣的事情发生在那里,即使你希望演员会以某种方式破坏事物(它不会,它只是一个演员和一个有效的演员)。
将该类的实例写入该文件,将其更改为serialVersionUID
,重新编译该类并尝试重新读取序列化对象。忘掉任何超级/子类的恶作剧。