2

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

我们在Java中声明的Serialization id是静态字段;而静态字段是不被序列化的。

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

4

4 回答 4

3

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

因此,stored如果它是实际定义的,它在编译的字节码中,否则它是计算的。用java 规范的话来说:

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

Stream Unique Identifiers 部分,解释了这种计算的算法。

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

注意:强烈建议所有可序列化的类都显式声明 serialVersionUID 值,因为默认的serialVersionUID 计算对类细节高度敏感,这些细节可能因编译器实现而异,因此可能会在反序列化过程中导致意外的 serialVersionUID 冲突,从而导致反序列化失败。

于 2012-04-20T07:31:52.840 回答
2

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

java.io.ObjectOutputStream.writeClassDescriptor(ObjectStreamClass)

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

java.io.ObjectStreamClass.getSerialVersionUID()

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

java.io.ObjectStreamClass.getDeclaredSUID(Class)

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

此处描述了如何阅读。

于 2012-04-20T07:29:40.423 回答
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
于 2012-04-20T07:33:30.577 回答
0

serialVersionUID是序列化运行时使用的特殊字段。这一切都在java.lang.Serializable的 Java 文档中进行了描述

于 2012-04-20T07:32:10.310 回答