我可能会冒着对此投反对票的风险。

在我看来,为新类显式指定serialVersionUID 是不好的。考虑两种情况:当布局应该改变时不改变它,以及当布局不应该改变时改变它。

几乎只有当它是明确的时候,才应该改变而没有改变。在这种情况下,它会导致一些非常微妙、难以发现的错误。特别是在开发过程中,类布局经常发生变化。但如果没有明确指定,它就会发生变化,反序列化将会严重中断,很可能通过清除存储库来解决。

几乎只有当它是隐式的时候才会发生不应该改变的情况。这是类布局已更改但我们仍然希望从旧的序列化 blob 进行反序列化的罕见情况。这可能会在质量检查期间被发现(从 5.2 升级到 5.2.1 后出现奇怪的错误,请参阅附加的堆栈跟踪)并且可以通过设置显式值来轻松修复。

评论?

有帮助吗?

解决方案

更改何时不应该出现类布局更改以外的原因 - 问题在于它依赖于编译器实现。如果您使用Eclipse进行调试但使用javac进行生产构建,则可能最终会出现两组不兼容的数据。

其他提示

在我的工作中,我们明确禁止指定serialVersionUID,正是因为您提出的问题。

另外,我们持久化的类只是用来存储数据,内部没有任何逻辑,所以它们改变的唯一方式就是改变数据成员。

进一步强调约翰双向飞碟说的话并与评论相矛盾:

"如果您不需要(即您总是使用相同的类版本序列化和反序列化),那么您可以安全地跳过显式声明“

即使您没有长期序列化并使用相同的类版本,仍然可能会出现问题。如果您正在编写客户端 - 服务器代码,并且客户端代码可以使用与服务器不同的jvm版本/实现,则可能会出现与不兼容的serialversionuids相同的问题。

总结一下,唯一时间是“安全”的。不指定serialversionuids是指您没有长期序列化并且保证序列化数据的所有使用者将使用与原始生产者相同的jvm实现和版本。

简而言之,使用serialversionuid通常是更有害的情况。

当您需要通过序列化支持长时间持久性时,您几乎总是需要使用自定义代码来支持这一点,并且需要显式设置 serialVersionUID ,否则旧的序列化版本将不会可以通过较新的代码进行反序列化。

这些场景已经需要非常小心,以便在类更改时使所有案例都正确,因此serialVersionUID是您遇到的最少问题。

如果你不需要它(即你总是使用相同的类版本序列化和反序列化),那么你可以安全地跳过显式声明,因为计算出的值将确保使用正确的版本。 / p>

无论你是否选择 serialVersionUID (我建议你这样做),你都应该考虑为串行兼容性创建一套全面的测试。

值得设计串行格式也值得。它实际上是一个公共API。

如果您只是使用序列化进行远程方法调用,例如调用EJB,其中客户端和服务器类和jvm是相同的,我怀疑这是最常见的用法,然后显式设置serialVersionUID(例如eclipse建议)可能会导致偶尔形式的重大痛苦,由于固定的serialVersionUID,不兼容的类实例被视为兼容的莫名其妙的错误。在低级别序列化期间,远程调用将无声地出错,并且只有在对象的状态不一致时才会出现问题。只有当您意识到客户端和服务器类在某种程度上不同时才能找到问题的根源(尽管serialVersionUID当然不是)。根据我的经验,为此设置serialVersionUID弊大于利。

另一方面,如果您显式设置serialVersionUID以读取旧数据,则根据定义,您将读取不兼容的版本,并且最终可能会出现处于不一致或不完整状态的对象。在这种情况下,设置serialVersionUID是针对不同问题的解决方法。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top