显式归零

时间:2009-03-25 07:30:28

标签: java

在java中哪些情况下显式归零有用。它是否以任何方式通过使对象无法访问或某些东西来帮助垃圾收集器?这被认为是一种好习惯吗?

7 个答案:

答案 0 :(得分:22)

在Java中,如果你有一个非常长时间运行的方法,可以帮助,并且对一个对象的唯一引用是通过局部变量。当您不再需要它时,将该局部变量设置为null(但是当该方法将继续运行很长时间时)可以帮助GC。 (在C#中,这很少有用,因为GC会考虑“最后可能的用途”。这种优化可能会让它在Java中出现一段时间 - 我不知道。)

同样,如果你有一个成员字段引用一个对象而你不再需要它,你可以通过将该字段设置为null来帮助GC。

但是,根据我的经验,很少实际对这些事情都很有用,而且会使代码更加混乱。很少有方法真正运行很长时间,将变量设置为null实际上与您希望方法实现的内容无关。当你不需要的时候这样做是不好的做法,如果你需要你应该看看重构是否可以改善你的设计。 (你的方法或类型可能做得太多了。)

请注意,将变量设置为null是完全被动的 - 它不会通知垃圾收集器可以收集对象,它只是避免垃圾收集器将该引用视为下次保持对象存活的原因( GC)运行。

答案 1 :(得分:9)

通常不需要(当然可以依赖于VM实现)。但是如果你有这样的东西:

private static final Map<String, String> foo;

然后在地图中包含您不再需要的项目,它们将无法进行垃圾回收,因此您需要明确删除它们。有很多这样的情况(事件监听器是另一个可能发生这种情况的领域)。

但做这样的事情:

void foo()
{
    Object o;

    // use o

    o = null; // don't bother doing this, it isn't going to help
}

编辑(忘了提这个):

如果您正在使用它,您应该会发现您声明的90-95%的变量可以是最终的。最终变量不能改变它指向的内容(或者它的基元值是什么)。在变量是最终的大多数情况下,在方法执行时接收不同的值将是错误(错误)。

如果您希望能够在使用后将变量设置为null,则它不能是最终的,这意味着您有更大的机会在代码中创建错误。

答案 2 :(得分:6)

我发现它有用的一个特例是当你有一个非常大的对象时,想要用另一个大对象替换它。例如,请查看以下代码:

BigObject bigObject = new BigObject();
// ...
bigObject = new BigObject(); // line 3

如果BigObject的实例太大而你在堆中只能有一个这样的实例,那么第3行将因OutOfMemoryError而失败,因为第3行中的赋值指令完成后才能释放第1个实例,这显然是在第二个实例准备就绪。

现在,如果你在第3行之前将bigObject设置为null:

bigObject = null;
bigObject = new BigObject(); // line 3

在构建第二个实例期间,当JVM用完堆时,可以释放第一个实例。

答案 3 :(得分:5)

来自“Effective Java”:使用它来消除过时的对象引用。否则会导致内存泄漏,这很难调试。

public Object pop(){
    if(size == 0)
        throw new EmptyStatckException();
    Object result = elements[--size];
    elements[size] = null; //Eliminate Object reference
    return result;
}

答案 4 :(得分:3)

如果在方法块关闭时无论如何都要使一个即将超出范围的对象归零,那么在垃圾收集方面没有任何好处。遇到那些不理解这一点的人并不罕见,他们很难将不必要的事情搞得很多。

答案 5 :(得分:1)

另请参阅J2SE中的WeakReference

答案 6 :(得分:1)

在以下所有情况都属实的罕见情况下,显式归零可以帮助GC:

  • 变量是对象的唯一(非弱)引用
  • 您可以保证不再需要该对象
  • 变量将在范围内延长一段时间(例如,它是长期对象实例中的字段)
  • 编译器无法证明该对象不再使用,但您可以通过对代码的高级逻辑分析来保证这一点: - )

在实践中,这在很好的代码中是非常罕见的:如果不再需要该对象,通常应该在更窄的范围内声明它。例如,如果在单个调用方法期间只需要对象,则它应该是局部变量,而不是封闭对象中的字段。

显式归零真正有用的一种情况:如果使用null来表示特定状态,那么设置为空值有时是必要且有用的。由于以下几个原因,Null本身是一个有用的值:

  • 空检查非常快,因此检查null的条件代码通常比许多替代方法更有效(例如,调用object.equals())
  • 如果您尝试取消引用它,则会立即获得NullPointerException。这很有用,因为它是一种很好的Fail Fast编码样式,可以帮助您捕获逻辑错误。