需要更多说明finalize(),样本考试

时间:2014-02-12 18:07:25

标签: java scjp

假设:

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是正确的,我不明白为什么,有人可以解释这里发生的事情。

1 个答案:

答案 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不是。