序列化中参考共享的含义是什么? 枚举如何序列化?

我正在阅读ObjectOutputStream文档并阅读有关序列化的内容,我有一些困惑。 它说明了这一点

使用引用共享机制对对单个对象的多个引用进行编码,以便可以将对象的图形恢复为与写入原始图像时相同的形状。

refence共享机制的含义是什么? 它还说明了这一点

枚举常量的序列化与普通的可序列化或可外部化的对象不同。 枚举常量的序列化forms仅由其名称组成; 不传输常量的字段值。 为了序列化枚举常量,ObjectOutputStream写入由常量名称methodLike返回的其他可序列化或可外化对象返回的字符串,枚举常量可以作为随后出现在序列化流中的后向引用的目标。

我能想到的一个原因是,因为Enum字段是常量,所以它们不会被序列化。 那么我们是否需要序列化枚举呢? 另一件事,如果状态不能序列化,为什么编译器不限制我们序列化枚举? 枚举常量可以作为反向引用的目标是什么意思?

请帮助澄清这个疑问。 谢谢。

使用引用共享机制对对单个对象的多个引用进行编码,以便可以将对象的图形恢复为与写入原始图像时相同的形状。

这意味着可以序列化包含循环的对象图。

换句话说,如果要序列化以下图表:

A – > B – > C – > A(C指回A)。

如果序列化A,它将执行以下操作:

  1. 序列化A.
  2. 走A的对象树,找到B
  3. 序列化B的简单字段
  4. 走B的对象树,找到C
  5. 序列化C的简单字段
  6. 走C的对象树,找到A
  7. 指针发送到流下方的A.

如果它没有这样做,那么序列化A将导致无限循环。

枚举常量的序列化与普通的可序列化或可外部化的对象不同。 枚举常量的序列化forms仅由其名称组成; 不传输常量的字段值。 要序列化枚举常量,ObjectOutputStream会写入常量名称方法返回的字符串

因为枚举是常量,所以假设它们在使用它们的地方总是具有相同的状态,因此不必向下发送枚举的状态。 因此,当接收方接收并枚举时,它只是查找该枚举的对象,并将其作为枚举返回,即使两侧的两个枚举可能具有不同的状态。

使用引用共享机制对单个对象的多个引用进行编码意味着:

如果您有一个对象图,那么该图中的每个对象仅被序列化一次,而不管该图中对它的引用数量。 例如,如果在图形中有对象A,B,C和D,则:

在此处输入图像描述

虽然可以通过路径A – > B – > D和A – > C – > D到达对象D,但是对象序列化机制足够智能,可以识别当它通过第二条路径到达它时已经序列化了对象D.所以不要再次尝试序列化它。 我怀疑(虽然从来没有仔细研究过),对象图在参考术语中被序列化,每个对象只有它的主要和存储参考。 这不仅对于最小化序列化对象图的大小而且在处理循环引用时也很重要。

枚举常量的序列化方式与普通的可序列化或可外部化的对象不同 ,因为正如您所说, Enum旨在成为常量。 虽然可以解决这个问题,但是当在另一个JVM中取消激活时,在一个JVM中序列化的枚举会出现不同,这可能是将运行时状态添加到枚举中的结果。

第一个问题:这意味着明显的事情。 如果对象出现多次,它将被序列化一次。 即:

Something s1 = new Something(), s2 = new Something(); List list = new ArrayList<>(); list.add(s1); list.add(s2); list.add(s2); list.add(list); 

将序列化两个对象,在数组列表的两个插槽中共享对s2对象的引用。 即使你有循环依赖(list包含对它自己的引用),它也会被正确处理 – 对象图按原样传输。

枚举序列化意味着另一个显而易见的事情。 它使用枚举名称进行序列化和反序列化。 如果您序列化某些内容,通过网络发送它,并使用不同版本的枚举类反序列化,则会执行此操作。 例如,当你序列化enum a时:

 class MyEnum {a,b,c} 

然后在另一个具有这样的枚举的JVM中反序列化:

 class MyEnum {aa, a, bb, c, d} 

尽管枚举的位置(序数)发生了变化,并且可能还有一些其他function(如哈希码a值),你将获得相同a值。