java-什么时候必须更改serialVersionUID?

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

什么时候必须更改serialVersionUID?

Kyle asked 2020-02-13T22:31:36Z
5个解决方案
51 votes

当对类的结构进行不兼容的更改时,最好更改serialVersionUID字段的值。 列出了不兼容更改的完整列表在Java对象序列化规范中。

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

Vineet Reynolds answered 2020-02-13T22:31:54Z
22 votes

关于每次更改班级都更改readObject()/writeObject()的屡屡口头禅是完整的,而且毫无意义。 请参阅此Sun文章,他们在他们的网站上重新发布了该文章,并在收购之后将其迁移到Oracle技术网。

仅当您故意要破坏与所有现有序列化的兼容性时,或者对类的更改如此激进以至于别无选择时,才应更改readObject()/writeObject(),在这种情况下,您应该真正考虑一下自己是什么。 实际在做。

在所有其他情况下,您都应该尝试使用自定义readObject()/writeObject()和/或writeReplace()/readResolve()方法和/或serialFields批注来破坏您的锅炉,以便您可以继续从这些现有序列化中读取对象。 一旦休息,您就会感到头疼,甚至噩梦。

user207421 answered 2020-02-13T22:32:24Z
4 votes

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

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

一个警告,我亲自经历了Serializable类的痛苦,这些类最初是为长期存储而设计的,但设计不当。 例如,将GUI元素存储在磁盘上,而不是在需要时创建它们。 问问自己,Serializable是否真的是保存数据的最佳方法。

Tom G answered 2020-02-13T22:32:56Z
1 votes

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

  • 删除栏位
  • 将类上移或下移
  • 将非静态字段更改为静态或将非瞬态字段更改为瞬态
  • 更改原始字段的声明类型
  • 更改writeObject或readObject方法,使其不再写入或读取默认字段数据,或者对其进行更改,以使其尝试写入或读取默认字段数据,而先前版本则不这样做。
  • 将类从可序列化更改为可外部化,反之亦然
  • 将类从非枚举类型更改为枚举类型,反之亦然
  • 删除可序列化或可外部化
  • 将writeReplace或readResolve方法添加到类
Malt answered 2020-02-13T22:33:56Z
-1 votes

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

唯一必须更改的是,如果您已经将一些数据序列化到文件中并且想要读取它。 如果由于某种原因它已更改,则必须将serialiVersionUID设置为文件中的版本,以希望能够读取数据。

Peter Lawrey answered 2020-02-13T22:34:21Z
translate from https://stackoverflow.com:/questions/3284979/when-do-i-have-to-change-the-serialversionuid