将Java对象设置为null是否会再执行任何操作?

我正在浏览一些旧书,并找到了Peter Hagger的“Practical Java”。 在性能部分中,建议在不再需要时将对象引用设置为null

在Java中,将对象引用设置为null提高性能或垃圾回收效率? 如果是这样,在什么情况下这是一个问题? 容器类? 对象组成? 匿名内部课程?

我经常在代码中看到这个。 这是现在过时的编程建议还是仍然有用?

当你想要归零引用时,这取决于一点。

如果你有一个对象链A-> B-> C,那么一旦A无法到达,A,B和C都将有资格进行垃圾收集(假设没有其他东西指的是B或C)。 例如,没有必要,也从来没有需要将引用A-> B或B-> C显式设置为null。

除此之外,大多数时候问题并没有真正出现,因为实际上你正在处理集合中的对象。 您通常应该始终考虑通过调用适当的remove()方法从列表,地图等中删除对象。

曾经有一些建议来设置对null的引用的情况特别是在一个很长的范围内,在这个范围内,内存密集型对象在范围的中途停止使用 。 例如:

 { BigObject obj = ... doSomethingWith(obj); obj = null; <-- explicitly set to null doSomethingElse(); } 

这里的基本原理是因为obj仍然在范围内,所以没有引用的显式归零,它在doSomethingElse()方法完成之后才会变为垃圾收集。 这是现代JVM可能不再适用的建议:事实certificate,JIT编译器可以在不再使用给定本地对象引用的哪个位置进行计算。

不,这不是过时的建议。 悬空引用仍然是一个问题,特别是如果您使用预先分配的数组实现可扩展数组容器( ArrayList等)。 超出列表“逻辑”大小的元素应该被删除,否则它们将不会被释放。

请参阅Effective Java 2nd ed,Item 6:Eliminate Obsolete Object References。

实例字段,数组元素

如果存在对对象的引用,则不能对其进行垃圾回收。 特别是如果那个对象(以及它后面的整个图形)很大,那么只有一个引用可以阻止垃圾收集,并且不再需要该引用,这是一个不幸的情况。

病态案例是保留用于配置它的整个XML DOM树,未注册的MBean或从未部署的Web应用程序对对象的单一引用的对象,该对象阻止整个类加载器被卸载。

因此,除非您确定持有引用本身的对象无论如何都要进行垃圾收集(或者甚至是那时),否则您应该将您不再需要的所有内容都清零。

范围变量:

如果您正在考虑在其作用域结束之前将局部变量设置为null,以便垃圾回收器可以回收并将其标记为“从现在开始无法使用”,则应考虑将其置于更有限的范围内。

 { BigObject obj = ... doSomethingWith(obj); obj = null; // <-- explicitly set to null doSomethingElse(); } 

 { { BigObject obj = ... doSomethingWith(obj); } // <-- obj goes out of scope doSomethingElse(); } 

长而扁平的范围通常也不利于代码的易读性。 引入私有方法以便为此目的进行分解并不是闻所未闻。

在内存限制性环境(例如手机)中,这可能很有用。 通过设置null,objetc不需要等待变量超出范围以获得gc’d。

然而,对于日常编程,这应该不是规则,除了像Chris Jester-Young所引用的特殊情况。

首先,它并不意味着您将对象设置为null。 我在下面解释一下:

 List list1=new ArrayList(); List list2=list1; 

在上面的代码段我们正在做的事情,实际上我们正在创建存储在内存中的ArrayList Object的对象引用变量名list1。 因此list1引用该对象,它注意的不仅仅是变量。 在第二行代码中,我们将list1的引用复制到list2中。 如果我这样做,现在回到你的问题:

 list1=null; 

这意味着list1不再引用存储在内存中的任何对象,因此list2也没有任何内容可供引用。 所以,如果你检查list2的大小:

 list2.size(); //it gives you 0 

所以这里垃圾收集器的概念到了,它说“你没有什么可担心释放对象所拥有的内存,当我发现它将不再用于程序并且JVM将管理我时,我会这样做。”

我希望它清楚这个概念。

这样做的原因之一是消除过时的对象引用。 你可以在这里阅读文字。