再回首Java第二十三天
序列化版本问题
由于反序列化Java对象时必须提供该对象的class文件,现在的问题是随着项目的升级,系统class文件也会升级,Java如何保证两个class文件的兼容性呢
Java序列化机制允许为序列化类提供一个private static final 的serialVersionUID属性值,该属性用于该Java类的序列化版本,也就是说如果一个类升级后,只要它的serialVersionUID属性值保持不变,序列化机制也会把它们当成同一个序列化版本
为了在反序列化时,确保序列化版本的兼容性,最好为每个要序列化的类加入private static final long serialVersionUID属性,具体的数值自己定义。这样,即使某个对象在被序列化之后,它所定义的类作出了修改,该对象仍然可以被正常地反序列化
若果不显示定义serialVersionUID,该属性值将由JVM根据类的相关信息计算得出,而修改后的类的计算结果往往跟修改前的计算结果不同,这就会造成对象反序列化因版本不兼容而失败
我们可以通过JDK安装路径中bin目录下的serialver.exe工具来获得类的serialVersionUID值
serialver Person
serialver -show Person还可以启动一个图形用户界面
不显示定义serialVersionUID值的另一个坏处是,不利于程序在不同的JVM中移植,因为不同编译器计算此属性值的策略不一样,从而造成即使类完全没有改变,在反序列化对象时也会因为版本的不兼容,而无法正确的反序列化的现象。
如果对类的修改确实会导致反序列化失败,我们应该重新为该类分配一个serialVersionUID值
三种情形类的修改
如果类仅仅是修改了方法,则反序列化则完全不受影响,类定义无须修改serialVersionUID值
如果类仅仅是修改了静态属性和瞬时属性(transient),则反序列化完全不受影响,类定义无须修改serialVersionUID值
如果类修改了非静态属性,非瞬时属性,则可能导致序列化版本不兼容,如果对象流中和新类包含了同名属性,而属性类型不同,则反序列化失败,应该更新类的serialVersionUID值。如果对象流中包含了比新类中更多的属性,则多出的属性会被忽略,序列化版本可以兼容,类定义可以不用更改serialVersionUID值;如果新类中包含了比对象流中更多的属性,序列化版本可以兼容,类定义可以不用更改serialVersionUID值,但反序列化得出的新的对象中多出的属性值都是默认值:引用类型为null,基本数值类型为0