为什么没有serialVersionUID
自动生成?我在应用程序服务器上遇到了一个问题,显然一个旧类正在被缓存。
3 回答
serialversionuid 不会自动生成,因为它很危险。当设置了 serialversionuid 时,这意味着一个类的两个版本在序列化方面是兼容的。
假设您有一个名为 Foo 的类,它没有 serialversionuid(默认值),并且您将 Foo 的一个实例序列化到一个文件中。稍后,您将一些新成员添加到 Foo 类。如果您尝试从文件中反序列化 Foo 对象,您将收到序列化失败,说明对象不兼容。它们不兼容,这是您想要的并且是默认设置。它们是不兼容的,因为 Foo 类中的新成员无法从 Foo 的旧序列化实例初始化。
现在,您可能会说,“我不在乎,在我的应用程序中,这些字段未初始化是可以接受的”。如果确实如此,您可以将新Foo 类的 serialversionuid 设置为与旧Foo 类相同。这将告诉 Java 对象在可序列化方面是兼容的,并且当您将旧的 Foo 实例反序列化为新的 Foo 类时,Java 不会抱怨(但新字段仍将未初始化)。
如果您是第一次创建一个新类,并且您设置了 serialversionuid,那么您正在输入一个 contract。该合同是,“对于具有相同 serialversionuid 的此类的所有未来版本,我将保证它们在状态和序列化方面是兼容的”。
如果您更改了一个类,并且您明确希望禁止对旧版本进行反序列化,则可以将 serialversionuid 更改为新值。如果尝试将旧对象反序列化为新的类实例,这将导致抛出异常。
它是根据类的结构自动生成的。如果结构发生变化,则重新生成 id(根据序列化规范,它是类的 hashof)。
所以你最好定义一个明确的serialVersionUID
.
如果您使用 Eclipse 作为您的 IDE,您可以右键单击有关缺少 serialVersionUID 的警告,您将获得两个选项:
1)定义Eclipse默认值,值为1L;或
2) 定义一个随机生成的 long 值
如果您关心序列化对象的版本控制,则每次修改类时都需要手动重新生成一个新值。Serializable 接口的 Javadoc 说明了如果您根本不声明 serialVersionUID 会发生什么:
如果可序列化类没有显式声明 serialVersionUID,则序列化运行时将根据类的各个方面为该类计算默认的 serialVersionUID 值,如 Java(TM) 对象序列化规范中所述。但是,强烈建议所有可序列化的类都显式声明 serialVersionUID 值,因为默认的 serialVersionUID 计算对类细节高度敏感,这些细节可能因编译器实现而异,因此可能在反序列化期间导致意外的 InvalidClassExceptions。因此,为了保证在不同的 java 编译器实现中具有一致的 serialVersionUID 值,可序列化的类必须声明一个显式的 serialVersionUID 值。
在实践中,我发现即使您在两台或多台机器上使用相同的源代码(例如,从 Subversion 签出),其中在类中未定义 serialVersionUID,编译器生成的类中的值在每个机器上都是不同的编译代码时的机器。这可能会在开发过程中导致令人困惑的错误。
如果您确定永远不会遇到过时的序列化对象与较新版本的类不同步的情况(或者两个 JVM 相互发送不同步的序列化对象,可能跨越网络或套接字连接)然后只需将 serialVersionUID 的值设置为 1L 并永远保持这种状态。
http://download-llnw.oracle.com/javase/6/docs/api/java/io/Serializable.html