Java Deep Copy 实用程序如何保留对象的内部关系?



我使用apacheSerializationUtils深度复制对象,发现了一些惊人的东西。例如,对象A有两个成员B1B2,并且它们都有相同的成员C(引用同一对象(。在深度复制之后,创建了A',并且我期望B1'具有成员C1'B2'具有成员C2'。但是出现了B1'B2'都具有相同的成员C'的情况。

似乎在深度复制之后,对象层次结构和关系得以保持。这是如何实现的?

如果两个引用指向同一个对象,那么我们将它们视为具有"相同标识"。也就是说,给定:

Object a = ...;
Object b = ...;

如果这一点成立,则ab是"相同的":a == b,仅当它们指向同一对象时才成立。

注意,a.equals(b)是不同的;对其成立的任何两个引用都可以被视为"相等",但可能涉及2个对象。琐碎的例子:

String a = new String("Hello");
String b = new String("Hello");
a == b; // this is false
a.equals(b); // this is true

可以计算出两个引用是否相同,而不仅仅是相等

一个简单的检查就是我刚刚向您展示的:==,它检查相同和不相等

最有可能的是,SerializationUnits中的代码使用WeakHashMap,这是一个映射到标识(或多或少是"指针"(的映射。WHM主要是一个内部实现,但请注意,您总是可以通过System.identityHashCode获得标识哈希代码,该代码为同一对象返回相同的值,即使该对象发生了变异。理论上,a.hashCode()可以返回不同的值(对于可变对象,它往往会返回(,但对于VM的生命周期中的任何给定实例,System.identityHashCode(a)都是相同的值。

Plain janeHashMap使用a.hashCode()来知道要查看哪个bucket,然后使用a.equals(b)来扫描是否相等。

WeakHashMap使用System.identityHashCode(a)来知道要查看哪个bucket,然后使用a == b来扫描相等性。

有了这一点,编写一个保持层次结构和关系的序列化程序就变得微不足道了。

还要注意,如果没有这样的机制,实体序列化是不可能的。毕竟,想象一下这个结构:

List<Object> list = new ArrayList<Object>();
list.add(list); // ooooh, recursion!

如果没有像WeakHashMap这样的工具,任何序列化此构造的尝试都将导致StackOverflowError,原因很明显。

我不知道Apache库,但很可能它保存了迄今为止复制的实例映射。如果遇到要复制的实例C,则首先检查该实例的副本C'是否已经存在。如果是,则使用现有副本。如果没有,它将创建C的深度副本,给出C',并将该副本存储在映射中。

需要考虑的一点是:我想Apache的存在性测试基于==运算符,而不是equals()方法,因为==运算符将给出最干净的结果,最类似于原始引用结构。如果不是,恰好满足equals()测试的两个不同实例C1C2将最终成为单个副本C'

最新更新