我什么时候需要更改serialVersionUID?

时间:2010-07-19 20:51:46

标签: java serialization

我知道我可以使用serialVersionUID来控制类的版本。我读到我可以添加或删除字段,类仍然兼容,它只使用默认值。

必须时,我更改了serialVersionUID?

5 个答案:

答案 0 :(得分:48)

当对类的结构进行不兼容的更改时,理想情况下应更改serialVersionUID字段的值。列出了不兼容更改的完整列表 在Java Object Serialization Specification

要进一步扩展,对类的不兼容更改将阻止反序列化机制创建对象的实例,因为流中的信息未映射到当前类定义。

答案 1 :(得分:20)

每次改变课程时,经常重复的关于改变serialVersionUID的口头禅是完整的,完全是胡说八道。请参阅他们在其网站上重新发布的this Sun article,并在收购后将其迁移到Oracle技术网。

如果您故意想要破坏与所有现有序列的兼容性,则应更改serialVersionUID ,例如,当您的课程更改时在语义上有所不同,你别无选择 - 在这种情况下你应该多次思考你实际上在做什么。

在所有其他情况下,您应该尝试使用自定义readObject()/writeObject()和/或writeReplace()/readResolve()方法和/或serialFields注释来破坏您的锅炉,以便您可以继续从现有的方法中读取对象序列化。一旦你打破了你的主要头痛,确实是噩梦。

答案 2 :(得分:3)

如果未在serialVersionUID类中指定Serializable字段,Java编译器将为您指定一个字段 - 实际上它是类名,接口名称,方法和方法的哈希值。班级的领域。但是,可以随时更改方法,因此,如果需要更改存储类的反序列化方式,则可以覆盖readObject方法。但是,如果确实在代码中指定了serialVersionUID字段,即使您确实进行了不兼容的更改,编译器也不会覆盖它,这可能会在运行时导致异常 - 您的IDE或编译器赢了不要给你一个警告。 (编辑 - 感谢EJP)如果你想轻松检查编译器如何查看某些更改,那么像Eclipse这样的IDE可以为你插入编译器的UID。

如果您经常进行更改,请保留旧版本的磁盘文件以测试反序列化。您可以编写单元测试来尝试读取旧文件,看看它是否有效或是否完全不兼容。

有一点需要注意,我个人经历过与最初用于长期存储而设计不当的Serializable类一起工作的痛苦。例如,将GUI元素存储在磁盘上而不是在需要时创建它们。问问自己Serializable是否真的是保存数据的最佳方式。

答案 3 :(得分:0)

为了完整起见,下面列出了一些更改,这些更改破坏了根据java 8 spec的Java序列化的兼容性:

  • 删除字段
  • 将类上移或下移
  • 将非静态字段更改为静态或将非瞬态字段更改为瞬态
  • 更改原始字段的声明类型
  • 更改writeObject或readObject方法,使其不再写入或读取默认字段数据,也对其进行更改,以便在以前的版本不这样做时尝试写入或读取它。
  • 将类从“可序列化”更改为“可外部化”,反之亦然
  • 将类从非枚举类型更改为枚举类型,反之亦然
  • 删除可序列化或可外部化
  • 将writeReplace或readResolve方法添加到类

答案 4 :(得分:-1)

您可以将serialiVersionUID设置为类的生命周期中的相同值。 (并不总是一个好主意)注意:如果需要,可以使用readObject / writeObject实现自己的序列化版本检查策略,并保持UID不变。

您必须更改它的唯一时间是您已经将某些数据序列化到文件中并且您想要读取它。如果因任何原因发生了变化,您必须将serialiVersionUID设置为文件中的版本,以便能够读取数据。