JAVA OBJECT GRAPH LAB

对象图、复制策略与可达性实验室

别先背“深”和“浅”。沿着引用箭头走一遍,看看究竟复制了哪一层、共享了哪一个对象。

一张图看清四种复制策略

橙色箭头来自变量根,绿色箭头是对象字段引用。修改副本 B 的城市后,观察 A 是否被连带改变。

堆中对象图
根可达 可回收候选 不可变对象
当前复制策略的对象引用图 变量 A 和 B 指向 Profile 对象,Profile 再指向 Address 对象。图会随复制策略、城市修改与根引用开关变化。

根引用决定“还能不能找到”

关闭根引用相当于让这个变量不再指向对象。对象是否成为候选,要看从所有仍存活的根出发还能否沿引用到达它。

边界要说清:“可回收候选”只表示从根不可达,不等于立刻回收;把变量设为 null 也不会强迫垃圾收集器马上工作。循环引用只要整体从根不可达,仍然可以成为回收候选。

把代码和对象图逐步对齐

每次只推进一步:先建原对象,再生成副本,最后观察修改传播。

clone() 提醒:调用 clone() 本身不能保证深复制;嵌套的可变引用若没有被显式复制,仍可能共享。判断复制深度,应检查完整对象图,而不是方法名。

四个小挑战

先在脑中沿箭头走一遍,再选择答案。每题会立即给出对象图层面的解释。

1. 执行 Profile b = a; 后,B 修改 address.city,A 会看到什么?

2. 浅复制创建了新 Profile,但直接复用原来的 Address 引用。哪一层仍共享?

3. A、B 两个根都断开,但 Profile 与 Address 互相引用形成环。这组对象的状态是?

4. 两个 Profile 共享不可变 Address;B 想换城市,哪种做法保持不可变约束?