当Java仍然在范围内时,Java能否最终确定它?
是。
但是,我在这里很迂腐。范围是一种确定名称有效性的语言概念。对象是否可以被垃圾收集(并因此最终确定)取决于它是否可达。
ajb的答案几乎得到了它(+1)引用了JLS的重要段落。但我不认为它直接适用于这种情况。JLS §12.6.1也说:一个可达的对象是可以在任何可能继续计算从任何活动线程访问的任何对象。
现在考虑将此应用于以下代码:class A {
@Override protected void finalize() {
System.out.println(this + " was finalized!");
}
public static void main(String[] args) {
A a = new A();
System.out.println("Created " + a);
for (int i = 0; i
if (i % 1_000_000 == 0)
System.gc();
}
// System.out.println(a + " was still alive.");
}}
在JDK 8 GA上,这将a每次都完成。如果你println在最后取消注释,a将永远不会最终确定。
通过println注释,可以看到可达性规则如何应用。当代码到达循环时,线程无法获得任何访问权限a。因此它无法访问,因此需要进行最终确定和垃圾收集。
请注意,名称a仍然在范围内,因为可以使用a封闭块中的任何位置 - 在本例中为main方法体 - 从其声明到块的末尾。JLS§6.3中涵盖了确切的范围规则。但实际上,正如您所看到的,范围与可达性或垃圾收集无关。
为了防止对象被垃圾收集,您可以在静态字段中存储对它的引用,或者如果您不想这样做,您可以稍后在相同的方法中使用它来保持它可访问 - 消费循环。调用一个无害的方法toString就足够了。