为什么要生成long serialVersionUID而不是简单的1L?

IAd*_*ter 204 java serialization code-generation serialversionuid

当类在Eclipse中实现Serializable时,我有两个选项:添加默认值serialVersionUID(1L)或生成serialVersionUID(3567653491060394677L).我认为第一个更酷,但很多时候我看到人们使用第二个选项.有没有理由生成long serialVersionUID

Mic*_*ers 86

据我所知,这只是为了兼容以前的版本.这只有在您之前忽略使用serialVersionUID,然后进行了一项您知道应该兼容但会导致序列化中断的更改时才有用.

有关更多详细信息,请参阅Java Serialization Spec.


coo*_*ird 69

序列化版本UID的目的是跟踪类的不同版本,以便执行对象的有效序列化.

我们的想法是生成一个特定版本的类所特有的ID,然后在添加到类中的新细节(例如新字段)时更改该ID,这会影响序列化对象的结构.

始终使用相同的ID,例如1L将来,如果类更改导致更改序列化对象的结构,则在尝试反序列化对象时很可能会出现问题.

如果省略ID,Java将根据对象的字段为您实际计算ID,但我认为这是一个昂贵的过程,因此手动提供一个将提高性能.

以下是一些文章的链接,这些文章讨论了类的序列化和版本控制:

  • 使用1L的想法是每次更改类属性或方法时都会增加它. (50认同)
  • 允许自动生成serialversionUID没有运行时性能影响 - 它是由javac在编译时生成的......如果你反编译类的字节码,你实际上会在字节码中静态地看到变量. (39认同)
  • @Jared根据Josh Bloch的Effective Java:第2版中的第75项:"在您编写的每个可序列化类中声明一个显式的串行版本UID ......如果没有提供串行版本UID,则需要在运行时生成一个昂贵的计算". (22认同)
  • @coobird这似乎是不建议使用默认serialVersionUID的主要原因`注意 - 强烈建议所有可序列化类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类详细信息高度敏感,可能因编译器实现而异,因此可能在反序列化期间导致意外的serialVersionUID冲突,导致反序列化失败.`以上评论来自Java Object Serialization Specification 6.0版 (11认同)
  • 还有一点需要注意 - 通过明确地管理数字,您可以决定何时考虑"兼容"类的版本,而不是要求类定义完全相同. (9认同)

Rob*_*bin 18

生成的主要原因是使其与已经存在副本的类的现有版本兼容.

  • 好的,但如果我总是 1L,也会一样。即使我做出任何改变,一切都将兼容。 (2认同)

Dav*_*itt 14

"long"缺省serialVersionUID值是Java序列化规范定义的缺省值,根据缺省序列化行为计算得出.

因此,如果您添加默认版本号,只要没有任何结构更改,您的类将(更快)序列化,但您必须注意,如果您更改类(添加/删除字段),您还需要更新序列号.

如果您不必与现有的比特流兼容,您可以放置1L并根据需要在发生变化时增加版本.也就是说,当更改的类的默认序列化版本与旧类的默认版本不同时.


Pan*_*mar 11

每次定义实现的类时,绝对应该创建一个serialVersionUID java.io.Serializable.如果不这样做,将自动为您创建一个,但这很糟糕.自动生成的serialVersionUID基于您的类的方法签名,因此如果您将来更改类以添加方法(例如),则反序列化该类的"旧"版本将失败.这是可能发生的事情:

  1. 创建类的第一个版本,而不定义serialVersionUID.
  2. 将类的实例序列化为持久性存储; 将自动为您生成serialVersionUID.
  3. 修改您的类以添加新方法,然后重新部署您的应用程序.
  4. 尝试反序列化在步骤2中序列化的实例,但现在它失败(何时应该成功),因为它具有不同的自动生成的serialVersionUID.

  • 事实上,反序列化该类的旧版本确实应该失败,因为它们不再相同了。您建议自己生成serialVersionUID,以防止类签名更改时导致(反)序列化失败。尽管您的建议是适当的,但您对其目的的解释完全是错误的和误导性的。修改你的答案是明智的。 (2认同)

joe*_*ker 6

如果你没有指定serialVersionUID,那么Java会动态生成一个.生成的serialVersionUID就是那个号码.如果您在类中更改某些内容并不会使您的类与以前的序列化版本不兼容但更改了哈希值,那么您需要使用生成的非常大数字的serialVersionUID(或错误消息中的"预期"数字) .否则,如果你自己跟踪所有事情,0,1,2 ......就更好了.