4

每当我们尝试serialize一个类的对象时,我们总是有一个唯一的值serialVersionId作为私有最终字段,它对 的意义是什么deserialization,我们可以用它来检查对象和值是否已以适当的方式反序列化?

4

3 回答 3

5

它用于检查序列化和反序列化是否使用了相同的类定义。直接来自文档

序列化运行时与每个可序列化类关联一个版本号,称为 serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已加载与序列化兼容的该对象的类。如果接收者为对象加载了一个类,该对象的 serialVersionUID 与相应发送者的类不同,则反序列化将导致 InvalidClassException。可序列化的类可以通过声明一个名为“serialVersionUID”的字段来显式声明自己的serialVersionUID,该字段必须是静态的、最终的和long类型:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

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

另外,请查看 Josh Bloch 的《Effective Java (2nd Edition)》一书:

自动生成的 UID 是根据类名、实现的接口以及所有公共和受保护的成员生成的。以任何方式更改其中任何一个都将更改 serialVersionUID。因此,只有当您确定不会超过一个版本的类被序列化(跨进程或稍后从存储中检索)时,您才需要弄乱它们。

如果暂时忽略它们,以后发现需要对类进行一些更改但要保持与旧版本类的兼容性,则可以使用JDK工具serialver在旧类上生成serialVersionUID,并显式设置新课上的那个。(根据您的更改,您可能还需要通过添加 writeObject 和 readObject 方法来实现自定义序列化 - 请参阅 Serializable javadoc 或上述第 11 章。)

于 2013-07-10T08:40:34.423 回答
0

当您使用不同的 VM或在不同的机器上对同一个类进行序列化和反序列化时,这一点很重要。UID 用于检查您尝试反序列化的类是否真的是您认为的那个,因此如果您的代码中的类具有一个 UID,而被序列化的类具有不同的 UID,则反序列化将失败。

JVM 会自动给一个没有 UID 的类,但不能保证不同的 JVM 会给同一个类提供相同的 UID。

你也可以参考这个,我从 SO 中找到的:

什么是 serialVersionUID,我为什么要使用它? http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

于 2013-07-10T08:41:09.490 回答
0

来自可序列化对象的文档

序列化运行时与每个可序列化类关联一个版本号,称为 serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已加载与序列化兼容的该对象的类。如果接收者为对象加载了一个类,该对象的 serialVersionUID 与相应发送者的类不同,则反序列化将导致 InvalidClassException。可序列化的类可以通过声明一个名为“serialVersionUID”的字段来显式声明自己的serialVersionUID,该字段必须是静态的、最终的和long类型:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

如果可序列化类没有显式声明 serialVersionUID,则序列化运行时将根据类的各个方面为该类计算默认的 serialVersionUID 值,如 Java(TM) 对象序列化规范中所述。但是,强烈建议所有可序列化的类都显式声明 serialVersionUID 值,因为默认的 serialVersionUID 计算对类细节高度敏感,这些细节可能因编译器实现而异,因此可能在反序列化期间导致意外的 InvalidClassExceptions。因此,为了保证在不同的 java 编译器实现中具有一致的 serialVersionUID 值,可序列化的类必须声明一个显式的 serialVersionUID 值。还强烈建议显式 serialVersionUID 声明尽可能使用 private 修饰符,因为此类声明仅适用于立即声明的类——serialVersionUID 字段不能用作继承成员。数组类不能显式声明 serialVersionUID,因此它们始终具有默认计算值,但数组类无需匹配 serialVersionUID 值。

有一个类似的线程。在这里检查

于 2013-07-10T08:41:17.460 回答