I am preparing for OCPJP, and I got stuck at the following mock exam question:
我正在为OCPJP做准备,我被困在以下模拟考试的问题:
Given:
考虑到:
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. }
When line 14 is reached, how many objects are eligible for the garbage collector?
当到达第14行时,有多少对象符合垃圾收集器的条件?
A. 0
答:0
B. 1
b . 1
C. 2
c . 2
D. 3
d . 3
E. 4
e . 4
F. 6
f . 6
Their correct answer is E, i.e. four objects, but I'm not sure why. From my point of view, i2 and its weight will get eligible for garbage collection. Perhaps I'm missing something, please advise.
他们的正确答案是E,即4个物体,但我不知道为什么。从我的观点来看,i2和它的重量将会得到垃圾回收的资格。也许我漏掉了什么,请告诉我。
3 个解决方案
#1
8
Lets call Icelandic()
on line 11 IceA
, line 12 IceB
, and so forth.
让我们把冰岛()称为第11行IceA,第12行IceB,等等。
After creation
创建后
i1 = IceA
i2 = IceB
i3 = IceC
After i3 = i1
i3 = i1后
i1 = IceA
i2 = IceB
i3 = IceA
After i1 = i2
i1 = i2后
i1 = IceB
i2 = IceB
i3 = IceA
After i2 = null
i2 =零后
i1 = IceB
i2 = null
i3 = IceA
After i3 = i1
i3 = i1后
i1 = IceB
i2 = null
i3 = IceB
So only the Icelandic()
created on line 12 remains. Now, each Icelandic()
has a Long weight
, so IceA
and IceC
are now unreferenced, meaning 4 objects (IceA
, IceA.weight
, IceC
, IceC.weight
) are available for GC.
所以只有在第12行创建的冰岛()仍然存在。现在,每个冰岛()都有很长的重量,所以IceA和IceC现在没有被引用,这意味着4个对象(IceA, IceA)。重量、IceC、IceC.weight)可供GC使用。
Other issues:
-
args
is stillargs
, they are not counting going out of scope in this question - args仍然是args,在这个问题中,它们不会超出范围。
-
Long weight
is not declared statically, so each instance of the class has aweight
object. - 长权重不是静态声明的,因此类的每个实例都有一个权重对象。
#2
3
Let's call the first Icelandic object that is created "A", the second one "B", and the third one "C". After line 12, they are referenced by i1, i2, and i3, respectively.
让我们调用第一个创建“A”的冰岛对象,第二个“B”,第三个“C”。在第12行之后,它们分别被i1、i2和i3所引用。
Now, we do:
现在,我们做的是:
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
So, objects "A" and "C" are no longer referenced, and they along with their "weight" are eligible for garbage collection, so four objects total.
因此,对象“A”和“C”不再被引用,它们与它们的“权重”一起符合垃圾收集的条件,因此总共有4个对象。
#3
2
You will have 4 objects in the system, 3 Icelandic
instances and 1 Long
instance.
系统中有4个对象,3个冰岛实例和1个长实例。
When you assign constant object to some variable, compiler uses kind of private static final Long long1200 = Long.valueOf(1200L);
object that is shared by all weight
instances.
当您将常量对象分配给某个变量时,编译器使用一种私有的静态final Long long1200 = Long.valueOf(1200L);所有权重实例共享的对象。
Primitive type wrappers are immutable, so it is safe to do this optimization.
原始类型的包装器是不可变的,所以这样做是安全的。
EDIT: probably I am wrong, because this would work this way if we referenced the same constant several times here, which is not the case
编辑:可能我错了,因为如果我们在这里引用相同的常量,这就会起作用,但事实并非如此。
#1
8
Lets call Icelandic()
on line 11 IceA
, line 12 IceB
, and so forth.
让我们把冰岛()称为第11行IceA,第12行IceB,等等。
After creation
创建后
i1 = IceA
i2 = IceB
i3 = IceC
After i3 = i1
i3 = i1后
i1 = IceA
i2 = IceB
i3 = IceA
After i1 = i2
i1 = i2后
i1 = IceB
i2 = IceB
i3 = IceA
After i2 = null
i2 =零后
i1 = IceB
i2 = null
i3 = IceA
After i3 = i1
i3 = i1后
i1 = IceB
i2 = null
i3 = IceB
So only the Icelandic()
created on line 12 remains. Now, each Icelandic()
has a Long weight
, so IceA
and IceC
are now unreferenced, meaning 4 objects (IceA
, IceA.weight
, IceC
, IceC.weight
) are available for GC.
所以只有在第12行创建的冰岛()仍然存在。现在,每个冰岛()都有很长的重量,所以IceA和IceC现在没有被引用,这意味着4个对象(IceA, IceA)。重量、IceC、IceC.weight)可供GC使用。
Other issues:
-
args
is stillargs
, they are not counting going out of scope in this question - args仍然是args,在这个问题中,它们不会超出范围。
-
Long weight
is not declared statically, so each instance of the class has aweight
object. - 长权重不是静态声明的,因此类的每个实例都有一个权重对象。
#2
3
Let's call the first Icelandic object that is created "A", the second one "B", and the third one "C". After line 12, they are referenced by i1, i2, and i3, respectively.
让我们调用第一个创建“A”的冰岛对象,第二个“B”,第三个“C”。在第12行之后,它们分别被i1、i2和i3所引用。
Now, we do:
现在,我们做的是:
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
So, objects "A" and "C" are no longer referenced, and they along with their "weight" are eligible for garbage collection, so four objects total.
因此,对象“A”和“C”不再被引用,它们与它们的“权重”一起符合垃圾收集的条件,因此总共有4个对象。
#3
2
You will have 4 objects in the system, 3 Icelandic
instances and 1 Long
instance.
系统中有4个对象,3个冰岛实例和1个长实例。
When you assign constant object to some variable, compiler uses kind of private static final Long long1200 = Long.valueOf(1200L);
object that is shared by all weight
instances.
当您将常量对象分配给某个变量时,编译器使用一种私有的静态final Long long1200 = Long.valueOf(1200L);所有权重实例共享的对象。
Primitive type wrappers are immutable, so it is safe to do this optimization.
原始类型的包装器是不可变的,所以这样做是安全的。
EDIT: probably I am wrong, because this would work this way if we referenced the same constant several times here, which is not the case
编辑:可能我错了,因为如果我们在这里引用相同的常量,这就会起作用,但事实并非如此。