serialVersionuId在序列化中的重要性?

时间:2013-07-10 08:39:18

标签: java

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

3 个答案:

答案 0 :(得分:5)

它用于检查相同的类定义是否用于序列化以及DeSerialization。直接从documentation

  

序列化运行时将每个可序列化类与版本号相关联,称为serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否已加载与该序列化兼容的该对象的类。如果接收者为具有与相应发送者类的serialVersionUID不同的对象加载了一个类,则反序列化将导致InvalidClassException。可序列化类可以通过声明名为“serialVersionUID”的字段来明确声明其自己的serialVersionUID,该字段必须是static,final和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(第2版):

  

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

     

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

答案 1 :(得分:0)

使用不同的虚拟机不同的计算机序列化和反序列化同一个类时非常重要。 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

答案 2 :(得分:0)

来自Serializable Object

的文件
  

序列化运行时与每个可序列化的类a关联   版本号,称为serialVersionUID,在此期间使用   反序列化以验证序列化的发送方和接收方   object已加载与该对象兼容的类   尊重序列化。如果接收器已加载了一个类   具有与其不同的serialVersionUID的对象   相应的发件人类,然后反序列化将导致   InvalidClassException。可序列化的类可以声明它自己的类   serialVersionUID通过声明一个名为的字段显式地显示   “serialVersionUID”必须是static,final和long类型:

     

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

     

如果是   serializable类没有显式声明serialVersionUID,   然后序列化运行时将计算默认值   该类的serialVersionUID值基于该方面的各个方面   class,如Java(TM)对象序列化中所述   规格。但是,强烈建议所有人   可序列化类显式声明serialVersionUID值,因为   默认的serialVersionUID计算对类非常敏感   细节可能因编译器实现而异,并且可以   因此导致意外的InvalidClassExceptions期间   反序列化。因此,要保证一致的serialVersionUID   不同java编译器实现的值,可序列化   class必须声明一个显式的serialVersionUID值。也是   强烈建议显式serialVersionUID声明使用   尽可能使用私有修饰符,因为此类声明仅适用于   立即声明的类 - serialVersionUID字段不是   作为继承成员有用。数组类不能声明显式   serialVersionUID,所以它们总是有默认的计算值,但是   免除匹配serialVersionUID值的要求   数组类。

有一个类似的线程。请检查此here