【发布时间】:2013-07-08 02:35:42
【问题描述】:
每当我们尝试serialize一个Class的对象时,我们总是有一个唯一值serialVersionId作为私有final字段,它相对于deserialization有什么意义,我们可以用它来检查是否对象和值是否已以适当的方式反序列化?
【问题讨论】:
-
哦..对不起..谢谢你的参考..
标签: java
每当我们尝试serialize一个Class的对象时,我们总是有一个唯一值serialVersionId作为私有final字段,它相对于deserialization有什么意义,我们可以用它来检查是否对象和值是否已以适当的方式反序列化?
【问题讨论】:
标签: java
当您使用不同的虚拟机或不同的机器对同一个类进行序列化和反序列化时,这一点很重要。 UID 用于检查您尝试反序列化的类是否真的是您认为的那个,因此如果您的代码中的类具有一个 UID,而被序列化的类具有不同的 UID,则反序列化将失败。
JVM 会自动给一个没有 UID 的类,但不能保证不同的 JVM 会给同一个类提供相同的 UID。
你也可以参考这个,我从 SO 中找到的:
What is a serialVersionUID and why should I use it? http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
【讨论】:
来自Serializable Object的文档
序列化运行时与每个可序列化类关联 版本号,称为serialVersionUID,用于 反序列化以验证序列化的发送者和接收者 对象已加载与该对象兼容的类 关于序列化。如果接收者已经为 对象的 serialVersionUID 与 对应的发件人的类,然后反序列化将导致 无效类异常。可序列化的类可以声明自己的 通过声明一个名为的字段显式 serialVersionUID "serialVersionUID" 必须是静态的、最终的和 long 类型:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
如果一个 可序列化类没有显式声明一个serialVersionUID, 然后序列化运行时将计算一个默认值 该类的 serialVersionUID 值基于 类,如 Java(TM) 对象序列化中所述 规格。但是,强烈建议所有 可序列化的类显式声明 serialVersionUID 值,因为 默认的 serialVersionUID 计算对类高度敏感 细节可能因编译器实现而异,并且可以 因此导致意外的 InvalidClassExceptions 在 反序列化。因此,要保证一致的serialVersionUID 跨不同 java 编译器实现的值,一个可序列化的 类必须声明一个显式的 serialVersionUID 值。也是 强烈建议显式 serialVersionUID 声明使用 可能的情况下使用私有修饰符,因为此类声明仅适用于 立即声明类--serialVersionUID 字段不是 作为继承成员有用。数组类不能显式声明 serialVersionUID,所以它们总是有默认的计算值,但是 匹配 serialVersionUID 值的要求被放弃 数组类。
有一个类似的线程。检查这个here
【讨论】:
用于检查序列化和反序列化是否使用了相同的类定义。直接来自documentation
序列化运行时将一个版本号与每个可序列化类相关联,称为 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 字段不能用作继承的成员。
另外,请查看 Josh Bloch 的《Effective Java (2nd Edition)》一书:
自动生成的 UID 是根据类名、实现的接口以及所有公共和受保护成员生成的。以任何方式更改其中任何一个都将更改 serialVersionUID。因此,只有当您确定不会对类的多个版本进行序列化(跨进程或稍后从存储中检索)时,才需要弄乱它们。
如果你暂时忽略它们,后来发现你需要以某种方式更改类但要保持与旧版本的类的兼容性,你可以使用JDK工具serialver在旧类上生成serialVersionUID,并在新类上明确设置。 (根据您的更改,您可能还需要通过添加 writeObject 和 readObject 方法来实现自定义序列化 - 请参阅 Serializable javadoc 或上述第 11 章。)
【讨论】:
serialVersionUID 与对象一起被序列化。此外,类定义应该存在于远程机器中以进行反序列化。