假设:
class Finalizer {
static int x = 0;
static boolean gc = false;
public static void main(String[] args) {
for(x=0; x<100000; x++) {
new Finalizer().finalize();
}
x = 0;
gc = true;
System.gc();
}
protected void finalize() {
if(gc == true) x++;
if(x % 10000 == 0)
System.out.println(gc + " " + x);
}
}
哪些都是真的? (选择所有适用的选项。)
A: true will never be an output
B: true will be output at least ones
C: If true and false are both output, their respective values for x can be the same.
D: If true and false are both output, their respective values for x can never be the same.
解决方案说C是正确的,我不明白为什么,有人可以解释这里发生的事情。
答案 0 :(得分:1)
这是怎么回事:finalize()
会覆盖Object
类中的方法。 javadoc解释何时调用此方法。当一个对象不再被引用时,它可能被垃圾收集;但何时它的垃圾收集不是由语言定义的。
当每个finalize()
对象被垃圾收集时,将调用Finalize
方法。当然,您发布的代码也会明确调用finalize()
。
在此示例中,循环将调用new Finalize()
100,000次以创建新的Finalize
个对象。每次创建一个新对象时,它都会用于显式调用finalize()
,但之后不再使用它,因此可以立即对其进行垃圾收集。这样做的结果是,当我们进入System.gc()
调用时,我们不知道有多少Finalize
个对象仍然在等待垃圾收集,但它可能是从0开始的任何地方到100,000。 (在我的机器上,它似乎是1.也就是说,除了其中一个对象之外,它已经被垃圾收集了,并在它们上面调用了finalize()
。)
在第一个循环中,x
将从0变为999,999(finalize()
方法不会修改x
),因此您应该看到每个false x
x
是10,000的倍数。 (请注意,运行时也可以为早期垃圾收集的对象调用finalize()
,因此理论上可以多次查看同一false x
x
。)< / p>
在第一个循环之后,如果 N 是仍然要进行垃圾收集的对象数,那么System.gc()
应该导致它们在那时被垃圾收集(它不是保证的);由于x
已重置为0且finalize()
将增加,这意味着x
将从1变为 N 。 (请注意,在finalize()
测试之前,第一个x
会将x % 10000
从0增加到1。)对于范围1中的每个true x
,您应该看到x
至 N 是10,000的倍数。
但是因为 N 可能是0到100,000之间的任何东西,这意味着我们可能会或可能不会看到任何true
输出 - 我们无法分辨。这就是为什么A和B都不是“永远都是真的”。如果我们确实看到任何true
输出,由于输出将在其范围内显示10,000的每倍数,因此可以确定true
输出将与先前的false
输出具有相同的数字,这解释了为什么C是正确的而D不是。