Java中的序列化版本uid

时间:2012-04-20 06:49:33

标签: java serialization

序列化ID如何存储在对象的实例中?

我们在Java中声明的序列化ID是静态字段;静态字段不是序列化的。

应该有一些方法来存储静态最终字段。 java是如何做到的?

4 个答案:

答案 0 :(得分:3)

serialVersionUID 未存储在“序列化”对象的实例中,因为它是一个静态字段(它是类的一部分,而不是对象的一部分)。

因此,如果实际定义了编译的字节码中的stored,则计算它。用java specification的话说:

  

如果类已定义serialVersionUID,则从类中检索它。如果serialVersionUID未由类定义,则根据虚拟机中类的定义计算。如果>指定的类不可序列化或可外部化,则返回null。

Stream Unique Identifiers section中,解释了这种计算的算法。

这一段值得注意(这就是为什么当实现Serializable的类没有明确定义serialVersionUID时,IDE通常会显示警告。)

注意 :强烈建议所有可序列化的类显式声明serialVersionUID值,因为默认的 serialVersionUID计算对类详细信息非常敏感可能因编译器实现 而异,因此在反序列化期间可能会导致意外的serialVersionUID冲突,从而导致反序列化失败。

答案 1 :(得分:2)

如果您查看java.io.ObjectStreamClass那里,您可以看到它实际上是序列化的。以下方法:

java.io.ObjectOutputStream.writeClassDescriptor(ObjectStreamClass)

调用一个调用以下方法的方法:

java.io.ObjectStreamClass.getSerialVersionUID()

要么计算serialVersionUID,要么使用在类中声明的并且在调用以下方法之前找到的那个:

java.io.ObjectStreamClass.getDeclaredSUID(Class)

所以看起来这个静态字段是静态字段未被序列化的规则的例外。

如何阅读here

答案 2 :(得分:2)

串行版UID不存储在对象中;它是一个静态字段,因此它存储在类定义中。发生的事情是,当您序列化对象时,还必须存储有关其类的信息;否则将无法取消序列化对象。存储的有关该类的信息包括其名称和序列版本UID。

您可以在此处阅读整个协议:http://docs.oracle.com/javase/6/docs/platform/serialization/spec/protocol.html

总之,新对象的条目恰好是:

newObject:
  TC_OBJECT classDesc newHandle classdata[]

这里classDesc是类的描述符,它可以是新类的声明,空引用或对先前声明的类的引用:

classDesc:
  newClassDesc
  nullReference
  (ClassDesc)prevObject

新类的声明建立了类的名称和序列版本UID,稍后可用于引用它的句柄,以及编码为classDescInfo的类的其他信息:

newClassDesc:
  TC_CLASSDESC className serialVersionUID newHandle classDescInfo

答案 3 :(得分:0)

serialVersionUID是序列化运行时使用的特殊字段。这些都在Java Doc中描述为java.lang.Serializable