显式serialVersionUID被认为有害吗?

时间:2009-01-07 10:00:21

标签: java serialization serialversionuid

我可能会冒这个风险投票。

在我看来,为新类明确指定serialVersionUID是不好的。考虑两种情况,即在布局应该更改时不更改它,并在不应该更改时更改它。

不应该更改它应该何时更改几乎只有在显式时才会发生。在这种情况下,它会导致一些非常微妙,难以发现的错误。特别是在开发过程中,当类布局经常变化时。但是如果它没有明确指定,它将会改变并且反序列化将大声破坏,最有可能通过清除存储库来解决。

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

评论

6 个答案:

答案 0 :(得分:19)

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

答案 1 :(得分:5)

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

此外,我们持久化的类仅用于存储内部没有逻辑的数据,因此它们改变的唯一方法是更改​​数据成员。

答案 2 :(得分:4)

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

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

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

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

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

答案 3 :(得分:2)

当您需要通过序列化支持长时间持久性时,您几乎总是需要使用自定义代码来支持这一点,并且需要显式设置serialVersionUID,否则旧的序列化版本将无法解除序列化通过更新的代码。

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

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

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

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