Java 我应该什么时候更改SerialUID?
我有一堆序列化的类。通常情况下,我会为它们生成序列UID,因为Java规则非常严格,基本上不做任何更改就可以重新创建序列号。但这让我想到了一个问题,我在互联网上找不到答案: 什么时候中断向后兼容性并手动更改类中的串行版本UID有意义?从: 序列化运行时将一个称为serialVersionUID的版本号与每个可序列化类相关联,该版本号在反序列化过程中用于验证序列化对象的发送方和接收方是否为该对象加载了与序列化兼容的类Java 我应该什么时候更改SerialUID?,java,serialization,Java,Serialization,我有一堆序列化的类。通常情况下,我会为它们生成序列UID,因为Java规则非常严格,基本上不做任何更改就可以重新创建序列号。但这让我想到了一个问题,我在互联网上找不到答案: 什么时候中断向后兼容性并手动更改类中的串行版本UID有意义?从: 序列化运行时将一个称为serialVersionUID的版本号与每个可序列化类相关联,该版本号在反序列化过程中用于验证序列化对象的发送方和接收方是否为该对象加载了与序列化兼容的类 我认为这是回答您问题的一个很好的提示:只要您以某种方式更改了类,序列化就会受到影
我认为这是回答您问题的一个很好的提示:只要您以某种方式更改了类,序列化就会受到影响(如添加/删除/更改序列化的类成员),那么您真的应该永远更改
serialVersionUID
的值。您应该组织自己,以便类在其整个生命周期中都具有相同的serialVersionUID。您应该(a)抵制对类的序列化不兼容更改;(b) 编写您自己的readObject()/writeObject()/readResolve()/writeReplace()对象,以便保留初始序列化格式,并在类的生命周期开始时定义显式serialVersionUID。当你改变这个值的时候,你的手就会非常头痛。计划避免它。Java规范第5.6节在这里提供了帮助:
5.6影响序列化的类型更改
有了这些概念,我们现在可以描述设计将如何应对
一个进化类的不同情况。这些案例如表1所示
由类的某个版本编写的流的术语。当溪流
是由同一版本的类读回的,没有丢失
信息或功能。这条小溪是唯一的水源
关于原始类的信息。它的类描述,而
原始类描述的子集,足以匹配
流中的数据,类的版本为
重组的
这些描述是从正在读取的流的角度进行的
以重新构造类的早期版本或更高版本。
用RPC系统的说法,这是一个“接收者使权利”
系统。作者以最合适的形式和
接收者必须解释该信息以提取其所需的部分
并填写不可用的部分
5.6.1不兼容的变更
类的不兼容更改是指
互操作性的保证无法维持。不相容
演化类时可能发生的更改包括:
- 删除字段-如果在类中删除字段,则写入的流将不包含其值。当流被 在前面的类中,该字段的值将设置为默认值 因为流中没有可用的值。但是,这是默认的 值可能会对早期版本的 履行合同
- 在层次结构中上下移动类-这是不允许的,因为流中的数据以错误的顺序出现
- 将非静态字段更改为静态字段或将非瞬态字段更改为瞬态字段-在依赖默认序列化时,此更改是无效的 相当于从类中删除字段。此版本的 类不会将该数据写入流,因此它不会 可供该类的早期版本阅读。当 删除字段时,将初始化早期版本的字段 设置为默认值,这可能导致类在意外情况下失败 方式
- 更改基元字段的声明类型-类的每个版本都使用其声明的类型写入数据。早期版本的 尝试读取字段的类将失败,因为 流中的数据与字段类型不匹配
- 更改writeObject或readObject方法,使其不再写入或读取默认字段数据,或更改它,使其 在以前的版本没有写入或读取时尝试写入或读取。这个 默认字段数据必须始终显示或不显示在中 小溪
- 将类从可序列化更改为可外部化或从可外部化更改为可外部化是不兼容的更改,因为流将包含 与可用类的实现不兼容
- 将类从非枚举类型更改为枚举类型或反之亦然,因为流将包含与 可用类的实现
- 删除Serializable或Externalizable是一个不兼容的更改,因为写入时将不再提供所需的字段 由类的旧版本创建
- 如果将writeReplace或readResolve方法添加到类中会产生 与该类的任何旧版本不兼容
- 添加字段-当要重构的类具有流中不存在的字段时,对象中的该字段将被删除 已初始化为其类型的默认值。如果特定于类 如果需要初始化,该类可能会提供readObject方法 可以将字段初始化为非默认值的
- 添加类-流将包含流中每个对象的类型层次结构。将流中的此层次结构与 当前类可以检测其他类。既然没有 从中初始化对象的流中的信息 类字段将初始化为t