我正在阅读ObjectOutputStream Documentation并阅读有关序列化的内容,我有一些困惑。它说明了
使用引用对单个对象的多个引用进行编码 共享机制,使对象的图形可以恢复到 与写原稿时的形状相同。
refence共享机制的含义是什么?它还说明了
枚举常量的序列化与普通的可序列化不同 或可外部化的对象。枚举常量的序列化形式 仅由其名称组成;常量的字段值不是 传输。要序列化枚举常量,ObjectOutputStream会写入 常量名称methodLike其他返回的字符串 可序列化或可外化的对象,枚举常量可以作为 随后出现在后面的参考目标 序列化流。
我能想到的一个原因是,因为Enum字段是常量,所以它们不会被序列化。 那么我们是否需要序列化枚举呢?另一件事,如果国家不能 为了序列化,为什么编译器不限制我们序列化枚举?是什么 这意味着,枚举常量可以作为反向引用的目标吗?
请帮助澄清这个疑问。感谢。
答案 0 :(得分:3)
使用引用对单个对象的多个引用进行编码 共享机制,使对象的图形可以恢复到 与写原稿时的形状相同。
这意味着可以序列化包含循环的对象图。
换句话说,如果要序列化以下图表:
A - > B - > C - > A(C指回A)。
如果序列化A,它将执行以下操作:
如果没有这样做,那么序列化A将导致无限循环。
枚举常量的序列化与普通的可序列化不同 或可外部化的对象。枚举常量的序列化形式 仅由其名称组成;常量的字段值不是 传输。要序列化枚举常量,ObjectOutputStream会写入 常量名称方法返回的字符串
因为枚举是常量,所以假设它们在使用它们的地方总是具有相同的状态,因此不必向下发送枚举的状态。因此,当接收方接收并枚举时,它只是查找该枚举的对象,并将其作为枚举返回,即使任何一方的两个枚举可能具有不同的状态。
答案 1 :(得分:1)
使用参考共享机制对单个对象的多个引用进行编码意味着:
如果您有一个对象图,那么该图中的每个对象仅被序列化一次,而不管该图中对它的引用数量。例如,如果在这样的图形中有对象A,B,C和D:
虽然可以通过路径A - >到达对象D. B - > D和A - > C - > D对象序列化机制足够智能,可以识别它在通过第二条路径到达它时已经序列化了对象D,因此不会尝试再次序列化它。我怀疑(虽然从来没有仔细研究过),对象图在参考术语中被序列化,并且每个对象都只有它的主要和存储参考。这不仅对最小化序列化对象图的大小很重要,而且对处理循环引用也很重要。
枚举常量的序列化方式与普通的可序列化或可外部化的对象不同,因为正如您所说,Enum旨在成为常量。虽然可以解决这个问题,但是当在另一个JVM中取消激活时,在一个JVM中序列化的枚举会出现不同,这可能是将运行时状态添加到枚举中的结果。
答案 2 :(得分:0)
第一个问题:这意味着明显的事情。如果对象出现多次,它将被序列化一次。即:
Something s1 = new Something(), s2 = new Something();
List<Object> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s2);
list.add(list);
将序列化两个对象,在数组列表的两个插槽中共享对s2
对象的引用。即使你有循环依赖(list包含对它自己的引用),它也会被正确处理 - 对象图按原样传输。
枚举序列化意味着另一个显而易见的事情。它使用枚举名称进行序列化和反序列化。如果您序列化某些内容,通过线路发送它,并使用不同版本的枚举类反序列化,则会执行此操作。例如。从序列化枚举a
时:
class MyEnum {a,b,c}
然后在另一个具有这样的枚举的JVM中反序列化:
class MyEnum {aa, a, bb, c, d}
尽管枚举的位置(序数)已更改,但您可能会获得相同的a
值,并且可能还有其他一些功能(如哈希码的值)。