在 Java 中将对象赋值为 null 是否会影响垃圾回收?

2022-08-31 11:54:06

在 Java 中分配一个未使用的对象引用是否会以任何可衡量的方式改进垃圾回收过程?null

我对Java(和C#)的经验告诉我,尝试和超越虚拟机或JIT编译器通常是违反直觉的,但我见过同事使用这种方法,我很好奇这是否是一个好的做法,或者是那些巫毒教编程迷信之一?


答案 1

通常不可以。

但就像所有事情一样:这要视情况而定。如今,Java中的GC非常好,在不再可访问之后,所有内容都应该在很短的时间内清理干净。这只是在为局部变量保留方法之后,并且不再为字段引用类实例时。

仅当您知道它将保持引用状态时,才需要显式空。例如,一个保留在周围的数组。当不再需要数组的各个元素时,您可能希望将其清空。

例如,ArrayList 中的以下代码:

public E remove(int index) {
    RangeCheck(index);

    modCount++;
    E oldValue = (E) elementData[index];

    int numMoved = size - index - 1;
    if (numMoved > 0)
         System.arraycopy(elementData, index+1, elementData, index,
             numMoved);
    elementData[--size] = null; // Let gc do its work

    return oldValue;
}

此外,显式清空对象不会导致对象被收集得比只要没有引用就自然超出范围更快。

双:

void foo() {
   Object o = new Object();
   /// do stuff with o
}

和:

void foo() {
   Object o = new Object();
   /// do stuff with o
   o = null;
}

在功能上是等效的。


答案 2

根据我的经验,人们经常出于偏执而不是出于必要而取消引用。以下是一个快速指南:

  1. 如果对象 A 引用对象 B,并且您不再需要此引用,并且对象 A 不符合垃圾回收的条件,则应显式清空该字段。如果封闭对象无论如何都要被垃圾回收,则无需清空字段。在 dispose() 方法中清空字段几乎总是无用的。

  2. 无需将方法中创建的对象引用清空。一旦方法终止,它们将自动清除。此规则的例外情况是,如果您在很长的方法或某个大型循环中运行,并且您需要确保在方法结束之前清除某些引用。同样,这些情况非常罕见。

我想说的是,绝大多数时候你不需要清空引用。试图智胜垃圾回收器是没有用的。你最终会得到低效,不可读的代码。