此问题来自Kathy Sierra SCJP 1.6。有多少个对象符合垃圾收集的条件?
根据Kathy Sierra的回答,这是C
。这意味着两个对象有资格进行垃圾回收。我给出了答案的解释。 但为什么c3
不符合garbage collection(GC)的条件?
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
} }
达到// Do stuff
时,有多少对象符合GC条件?
答案:
Short
包装器对象也符合条件。答案 0 :(得分:7)
让我们逐行打破这个:
CardBoard c1 = new CardBoard();
我们现在有两个对象,CardBoard
c1
点和Short
c1.story
。对于GC c1
以及CardBoard
点story
点CardBoard
变量Short
点,GC都不可用。
CardBoard c2 = new CardBoard();
与上面类似,我们现在有四个对象,其中没有一个可用于GC。
CardBoard c3 = c1.go(c2);
我们调用c1
指向的CardBoard上的方法,传递c2
的值,该值是对CardBoard
对象的引用。我们使参数为空,但Java是按值传递的,这意味着c2
变量本身不受影响。然后我们返回nullled参数。 c3
null
,c1
和c2
不受影响。我们仍然有4个对象,其中没有一个可以用GC。
c1 = null;
我们为c1
。 CardBoard
之前指出的c1
对象没有任何指向它的对象,它可以是GC。因为story
对象中的CardBoard
变量是唯一指向Short
的变量,并且因为CardBoard
对象符合GC的条件,Short
也是有资格获得GC。这给了我们4个对象,其中2个可以是GC'd。符合GC条件的对象是以前由c1
和c1.story
引用的对象。
答案 1 :(得分:6)
c3
指向的任何对象都不存在。构造函数仅被调用两次,两个对象,每个对象由c1
和c2
指向。 c3
只是一个引用,除了空指针之外从未分配任何东西。
当前指向null的引用c3
将不会超出范围并从堆栈中删除,直到超过main方法结束时的右括号。
最初分配给c1
的对象无法访问,因为c1
引用设置为null,但c2
引用尚未更改,因此分配给它的对象仍可访问来自此范围的c2
参考。
答案 2 :(得分:4)
c3
是null
,因此显然没有符合垃圾回收条件的对象。
请注意,只创建了两个CardBoard
个对象,这两个对象在这些行中:
CardBoard c1 = new CardBoard();
CardBoard c2 = new CardBoard();
在参考杂耍之后,其中只有一个没有参考。
答案 3 :(得分:1)
正式答案是我们不知道。我们不知道的原因是这一行:
Short story = 200;
这将编译为以下字节代码:
CardBoard();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: sipush 200
8: invokestatic #2 // Method java/lang/Short.valueOf:(S)Ljava/lang/Short;
11: putfield #3 // Field story:Ljava/lang/Short;
14: return
第8行是此处的关键字Short.valueOf()
,它返回原始200
的盒装等价物。让我们看一下Short.valueOf()
的Javadoc:
此方法将始终缓存-128到127范围内的值, 包含,并可以缓存此范围之外的其他值。
200超出“必须缓存”范围,因此它属于“可以缓存”。如果它被缓存,story
的值在包含CardBoard
实例的情况下将不符合GC的条件。如果未缓存,则story
将无法访问,因此无法进行GCed。
为了使问题明确(并且建议的答案正确),代码应该像这样修改:
Short story = new Short(200);
更新: Short.valueOf()
的{{3}}比我引用的1.8版本更加神秘,但同样的逻辑适用:没有办法只通过查看在代码中是否将返回Short
的新实例或缓存实例。
答案 4 :(得分:-1)
如果您注意到代码中只创建了两个对象。 c3永远不会初始化为对象,它是一个空引用。因此,只有一个“对象”符合垃圾收集条件。