serialVersionUID是什么?
当对象被序列化的同时,该对象(以及所有在其版图上的对象)都会被"盖"上一个类的版本识别ID。这个ID被称为serialVersionUID,它是根据类的结构信息计算出来的(如果不显示声明)。在对象被解序列化是,如果在对象被序列化之后类有了不同的serialVersionUID(),则解序列化还原对象操作会失败(会抛出serialVersionUID不一致异常)。
serialVersionUID的作用?
对序列化进行版本控制。
每次对象被解序列化时,会验证当前类的serialVersionUID是否和对象被序列化时保存到文件中的serialVersionUID是否一致。
若不一致,则认定序列化时和反序列化的类是不同的,不能进行反序列化操作。
为什么要显示声明serialVersionUID?
不声明->新版本类被修改了->serialVerisonUID不一致->新版本对旧版本序列化对象后的文件反序列化,号不一样->反序列化失败
不声明->新版本类被修改了->serialVerisonUID不一致->旧版本对新版本序列化对象后的文件反序列化,号不一样->反序列化失败
手动声明
->serialVersionUID在序列化时和反序列化时一致
->可以进行后续序列化操作
->反序列化时若类的属性字段比对象被序列化时类的属性字段多,那么该属性取默认值;若反序列化类的属性字段比序列化时类的属性字段少,那么忽略该属性字段正常进行反序列化;若反序列化时类的属性类型与被序列化的对象属性类型不一致,报异常。
- 如果不显示声明serialVersionUID,那么虚拟机会根据类的结构信息生成serialVersionUID。序列化时虚拟机会将serialVersionUID存储到文件中,解序列化虚拟机会类当前的serialVersionUID去和文件中的读取出的serialVersionUID做对比,不一致则抛出异常。
- 序列化不一致的情况
- 假设序列化对象时的虚拟机与解序列化时的虚拟机不一样,那么生成的serialVersionUID也有很大可能不一致,那么就会导致对象解序列化失败。
- 类的实例变量,方法等类的机构信息发生改变也会导致类的默认serialVersionUID变化。虚拟机会根据编译后的class文件重新为该类生成新的serialVersionUID。
- 因此若我们希望当前版本对象被序列化后的文件可以兼容未来的版本(可能会修改该对象的类信息),我们通常会在实现序列化接口后为serialVersionUID显示声明一个值。如 private static final long serialVersionUID = 1L; 这样以后反序列化时就不会因为serialVersionUID不一致而报错了。
参考文章
serialVersionUID作用^[http://swiftlet.net/archives/1268]