摘自SCJP 6预备书 -
假设:
class CardBoard {
Short story = 200;
CardBoard go(CardBoard cb) {
cb = null;
return cb;
}
public static void main(String[] args) {
CardBoard c1 = new CardBoard();
CardBoard c2 = new CardBoard();
CardBoard c3 = c1.go(c2);
c1 = null;
// do Stuff
}
}
当达到// doStuff时,有多少对象符合GC条件?
一个。 0
B中。 1
℃。 2
d。编译失败
电子。无法知道
F。在运行时抛出异常
正确的答案是C - “只有一个CardBoard对象(c1)符合条件,但它有一个相关的Short包装器对象也符合条件。”
我的问题是为什么c3不符合收集资格?
我的想法是 -
c1.go(c2)将本地引用变量cb(它是c2的副本)设置为null,然后返回分配给c3的cb。我知道c2本身的引用变量不能在方法中修改,只能修改它背后的对象。但是在我看来,引用变量cb的副本被设置为null并分配给c3。为什么在此实例中c3未设置为返回的null?
答案 0 :(得分:7)
没有与c3相关的对象。它的值为null,因此无需收集任何内容。
答案 1 :(得分:1)
SCJP“正确”的答案是虚假的。正确答案是4或“不可能知道”。
如果按字面读取代码(“// do Stuff”只是一个注释),那么之前从c2可以访问的对象就像死了一样,GC符合之前从c1引用的那个,并且因为这两个现在无法访问的对象有一个c1.story和c2.story对象,它们也会死掉它们,共有4个对象可以收集。
但是,如果“// do Stuff”的东西是某个未知代码的占位符,那么该代码可能会也可能不会使用c2,这意味着c2引用的对象可能已经或可能没有死亡且符合条件到达该代码时的集合。因此,如果我们不知道“// do Stuff”实际上是什么,那么它是2或4是合格的,并且没有办法分辨哪个。