为什么没有自动生成serialVersionUID?

发布于 2024-09-16 10:34:06 字数 75 浏览 2 评论 0原文

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

Why isn't the serialVersionUID automatically generated? I was running into an issue on an application server where apparently an old class was being cached.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

哽咽笑 2024-09-23 10:34:06

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

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

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

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

如果您更改类,并且明确想要禁止旧版本的反序列化,则可以将serialversionuid更改为新值。如果尝试将旧对象反序列化为新的类实例,这将导致引发异常。

serialversionuid is not automatically generated because it is dangerous. When serialversionuid is set, it implies that two versions of a class are compatible with respect to serialization.

Imagine you have a class called Foo, and it has no serialversionuid (the default), and you serialize an instance of Foo to a file. Later, you add some new members to the Foo class. If you try to deserialize the Foo object from the file, you will get a serialization failure stating that the objects are incompatible. They are incompatible, this is what you want and is the default. They are incompatible because new members in the Foo class cannot be initialized from the old serialized instance of Foo.

Now, you might say, "I don't care, in my application it is acceptable for those fields to be uninitialized". If that really is the case, you can set the serialversionuid of the new Foo class to be the same as the old Foo class. This will tell Java that the objects are compatible with respect to serializablity, and Java will not complain when you deserialize the old Foo instance into the new Foo class (but the new fields will still be uninitialized).

If you are creating a new class for the first time, and you set the serialversionuid, you are entering a contract. That contract is, "For all future versions of this class with the same serialversionuid, I will guarantee they are compatible with respect to state and serialization".

If you change a class, and you explicitly want to disallow deserialization of old versions, you can change the serialversionuid to a new value. This will cause an exception to be thrown if an old object is attempted to be deserialized into a new class instance.

你穿错了嫁妆 2024-09-23 10:34:06

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

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

It is automatically generated, based on the structure of the class. If the structure changes, the id is regenerated (according to the serialization specification it is a hashof the class).

So you'd better define an explicit serialVersionUID.

爱的十字路口 2024-09-23 10:34:06

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

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

如果您关心序列化对象的版本控制,则每次修改类时都需要手动重新生成新值。 Serialized 接口的 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/Serializing.html

If you're using Eclipse as your IDE, you can right-click on the warning about the missing serialVersionUID and you'll get two options:

1) Define the Eclipse default, which has the value 1L; or
2) Define a randomly generated long value

If you care about versioning of serialized objects, you'll need to manually regenerate a new value each time you modify the class. The Javadoc for the Serializable interface has this to say about what happens if you don't declare a serialVersionUID at all:

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value.

In practice, I've found that even if you start with identical source code on two or more machines (checked out of Subversion, for example) where serialVersionUID was undefined in a class, the compiler-generated value in the class is different on each machine when the code is compiled. This can cause confusing errors during development.

If you are sure that you'll never have a situation where you have stale serialized objects that are out-of-sync with a newer version of the class (or two JVMs sending out-of-sync serialized objects to each other, perhaps across a network or socket connection) then just set a value of 1L for serialVersionUID and leave it that way forever.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文