Java 增加可序列化对象定义的版本ID的有效原因是什么?

Java 增加可序列化对象定义的版本ID的有效原因是什么?,java,serialization,Java,Serialization,增加实现可序列化的类定义的版本ID的有效和无效原因是什么 换句话说,什么会导致先写后读的不兼容?对方法的更改是否有可能导致不兼容?重构有没有可能导致不兼容 编辑阅读链接和答案,我发现程序员定义的ID是控制自动ID的一种方式,它会使对象变得过于脆弱。如果我控制ID,那么我需要知道管理它的确切规则 根据这一点-如果我理解正确,如果您破坏了接口,您几乎必须更改版本ID,比如更改或删除签名 更改方法逻辑不会导致不兼容。不兼容版本的默认概念通常过于严格。如果您添加一个字段,它将更改默认的serialVer

增加实现可序列化的类定义的版本ID的有效和无效原因是什么

换句话说,什么会导致先写后读的不兼容?对方法的更改是否有可能导致不兼容?重构有没有可能导致不兼容

编辑阅读链接和答案,我发现程序员定义的ID是控制自动ID的一种方式,它会使对象变得过于脆弱。如果我控制ID,那么我需要知道管理它的确切规则

根据这一点-如果我理解正确,如果您破坏了接口,您几乎必须更改版本ID,比如更改或删除签名


更改方法逻辑不会导致不兼容。

不兼容版本的默认概念通常过于严格。如果您添加一个字段,它将更改默认的serialVersionUID,这将阻止您加载旧数据,即使这可能是一个良性更改。
事实上,流包含对象状态的完整描述,包括其所有字段的名称和类型。这些信息由系统存储,一般来说,您可以转换旧数据。系统还提供默认转换(跳过意外字段并将缺少的字段设置为默认值),这通常已经足够了,但如果serialVersionUID不匹配,则会禁用该转换。

这与版本控制系统中的版本设置类似。您发布了一些客户端正在使用的初始类定义

现在,稍后您更改了一些类定义。使用不同的类版本将使您现有的客户端可以毫无问题地工作


基于版本Id,兼容客户端可以正常工作

来自Oracle,为了解决这个问题,如果更改是兼容的,则不需要碰撞ID(“无效”),如果更改是不兼容的,则碰撞ID是“有效的”。

此链接对此主题进行了很好的讨论。它也有关于这个问题的一些好资源的链接。我认为序列化只携带数据,那么为什么方法签名很重要呢?@broiyan-你说得对,我会编辑它。你为什么在原来的问题中问这个问题?:)跳过意外字段和默认缺少的字段很好,但我想知道它是位置相关的还是标识符相关的?如果与标识符相关,则重构将破坏此有用功能。@broiyan它在写入的类型描述符中包含字段名。每个序列化的非原语非字符串类型只描述一次。血淋淋的细节:允许开发人员使用特定的serialversionuid的目的是消除JVM是否应该尝试读取存储类的任何歧义。否则,运行时将尝试加载该类,如果类的不兼容性太大,则可能会失败。失败可能是JVM实现特有的,但一般来说,简单地重新排序字段不会导致反序列化问题。