为什么不自动生成serialVersionUID?

时间:2010-08-25 19:44:46

标签: java serialization serialversionuid

为什么不自动生成serialVersionUID?我在应用程序服务器上遇到了一个问题,显然是在缓存旧类。

3 个答案:

答案 0 :(得分:22)

serialversionuid不会自动生成,因为它很危险。当设置serialversionuid时,它意味着类的两个版本在序列化方面是兼容的。

想象一下,你有一个名为Foo的类,它有 no serialversionuid (默认值),你将一个Foo实例序列化为一个文件。稍后,您将向Foo类添加一些新成员。如果您尝试从文件反序列化Foo对象,您将收到序列化失败,指出对象不兼容。他们 不兼容,这是你想要的并且是默认的。它们是不兼容的,因为无法从旧的Foo序列化实例初始化Foo类中的新成员。

现在,您可能会说,“我不在乎,在我的应用程序中,这些字段未被初始化是可以接受的”。如果确实是,则可以将 new Foo类的serialversionuid设置为与 Foo类相同。这将告诉Java这些对象与serializablity相关,并且当你将旧的Foo实例反序列化为新的Foo类时,Java不会抱怨(但是新的字段仍然是未初始化的。)

如果您是第一次创建新课程,并设置了serialversionuid,则 您正在输入合同 。该合同是,“对于具有相同serialversionuid的此类的所有未来版本,我将保证它们在状态和序列化方面兼容”

如果您更改了某个类,并且显式想要禁止旧版本的反序列化,则可以将serialversionuid更改为新值。如果尝试将旧对象反序列化为新的类实例,这将导致抛出异常。

答案 1 :(得分:9)

它是根据类的结构自动生成的。如果结构发生变化,则重新生成id(根据serialization specification,它是hashof类)。

所以你最好定义一个明确的serialVersionUID

答案 2 :(得分:2)

如果您使用Eclipse作为IDE,可以右键单击有关缺少的serialVersionUID的警告,您将获得两个选项:

1)定义Eclipse默认值,其值为1L;或
2)定义随机生成的长值

如果您关心序列化对象的版本控制,则每次修改类时都需要手动重新生成新值。 Serializable接口的Javadoc可以说明如果你根本没有声明serialVersionUID会发生什么:

  

如果可序列化类没有显式声明serialVersionUID,则序列化运行时将根据类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范中所述。但是,强烈建议所有可序列化类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类细节高度敏感,这些细节可能因编译器实现而异,因此在反序列化期间可能导致意外的InvalidClassExceptions。因此,为了保证跨不同java编译器实现的一致的serialVersionUID值,可序列化的类必须声明一个显式的serialVersionUID值。

实际上,我发现即使你在一个类中未定义serialVersionUID的两台或多台机器(例如从Subversion中检出)开始使用相同的源代码,类中编译器生成的值也是编译代码时每台机器上的不同。这可能会在开发过程中导致混淆错误。

如果您确定您将永远不会遇到与较新版本的版本不同步的过时序列化对象(或者两个JVM向对方发送不同步的序列化对象的情况) ,或者通过网络或套接字连接)然后只需为serialVersionUID设置1L的值,并永远保持这种状态。

http://download-llnw.oracle.com/javase/6/docs/api/java/io/Serializable.html