为什么不自动生成serialVersionUID?

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

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

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

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

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

如果更改类,并且明确禁止对旧版本进行反序列化,则可以将serialversionuid更改为新值。 如果尝试将旧对象反序列化为新的类实例,则会引发exception。

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

所以你最好定义一个显式的serialVersionUID

如果您使用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