Java中垃圾收集的合格变量

我正在为OCPJP做准备,我被困在以下模拟考试题目中:

鉴于:

3. interface Animal { void makeNoise(); } 4. class Horse implements Animal { 5. Long weight = 1200L; 6. public void makeNoise() { System.out.println("whinny"); } 7. } 8. public class Icelandic extends Horse { 9. public void makeNoise() { System.out.println("vinny"); } 10. public static void main(String[] args) { 11. Icelandic i1 = new Icelandic(); 12. Icelandic i2 = new Icelandic(); 12. Icelandic i3 = new Icelandic(); 13. i3 = i1; i1 = i2; i2 = null; i3 = i1; 14. } 15. } 

到达第14行时,有多少对象符合垃圾收集器的条件?

A. 0

B. 1

C. 2

D. 3

E. 4

F. 6

他们的正确答案是E,即四个物体,但我不确定为什么。 从我的角度来看,i2及其重量将有资格进行垃圾收集。 也许我错过了什么,请指教。

让我们在第11行IceA ,第12行IceA上调用Icelandic() ,依此类推。

创作之后

 i1 = IceA i2 = IceB i3 = IceC 

i3 = i1

 i1 = IceA i2 = IceB i3 = IceA 

i1 = i2

 i1 = IceB i2 = IceB i3 = IceA 

i2 = null

 i1 = IceB i2 = null i3 = IceA 

i3 = i1

 i1 = IceB i2 = null i3 = IceB 

所以只剩Icelandic() 12行创建的Icelandic() 。 现在,每个Icelandic()都具有Long weight ,因此IceAIceC现在IceC被引用,这意味着4个对象( IceAIceA.weightIceCIceC.weight )可用于GC。


其他问题:

  1. args仍然是args ,他们不计算这个问题超出范围
  2. Long weight不是静态声明的,因此类的每个实例都有一个weight对象。

让我们称之为第一个创建“A”的冰岛对象,第二个称为“B”,第三个称为“C”。 在第12行之后,它们分别由i1,i2和i3引用。

现在,我们做:

 i3 = i1; // object "C" is no longer referenced, object "A" is now referenced by i1 and i3 i1 = i2; // object "A" is just referenced by i3, object "B" is referenced by i1 and i2 i2 = null; // object "B" is just referenced by i1 now i3 = i1; // object "B" is referenced by i1 and i3, object "A" is no longer referenced 

因此,不再引用对象“A”和“C”,它们及其“权重”符合垃圾收集条件,因此总共有四个对象。

系统中将有4个对象,3个Icelandic实例和1个Long实例。

当你将常量对象赋给某个变量时,编译器会使用一种private static final Long long1200 = Long.valueOf(1200L); 所有权weight实例共享的对象。

原始类型包装器是不可变的,因此进行此优化是安全的。

编辑:可能我错了,因为如果我们在这里多次引用相同的常量,这将是这样的,但实际情况并非如此