Java 显式零位

Java 显式零位,java,Java,在java中,显式空值在什么情况下有用。它是否通过使对象不可访问或其他方式来帮助垃圾收集器?它被认为是一个好的实践吗?通常不需要它(当然,这可能取决于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 h

在java中,显式空值在什么情况下有用。它是否通过使对象不可访问或其他方式来帮助垃圾收集器?它被认为是一个好的实践吗?

通常不需要它(当然,这可能取决于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%的变量都是最终的。最后一个变量不能更改它所指向的对象(或者它的原语值)。在大多数情况下,当一个变量是final时,如果在方法执行时接收到不同的值,则是一个错误(bug)

如果您想在使用后将变量设置为null,那么它不能是final,这意味着您有更大的机会在代码中创建bug。

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

同样,如果您有一个引用对象的成员字段,并且不再需要它,那么您可以通过将该字段设置为null来帮助GC

然而,根据我的经验,做这两件事实际上很少有用,而且会使代码更加混乱。很少有方法能够长时间运行,而将变量设置为null实际上与您希望该方法实现的目标无关。在不需要的时候这样做是不好的做法,如果需要的话,首先应该看看重构是否能改善设计。(您的方法或类型可能做得太多。)


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

如果在方法块关闭时将要超出作用域的对象置零,则在垃圾收集方面没有任何好处。经常会遇到不理解这一点的人,他们非常努力地将很多东西不必要地设置为null。

另见J2SE。

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

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

我发现它非常有用的一个特殊情况是,当您有一个非常大的对象,并且希望用另一个大对象替换它时。例如,请查看以下代码:

BigObject bigObject = new BigObject();
// ...
bigObject = new BigObject(); // line 3
如果BigObject的实例太大,堆中只能有一个这样的实例,那么第3行将失败,并出现OutOfMemoryError,因为在第3行中的赋值指令完成之前,第一个实例无法释放,这显然是在第二个实例准备就绪之后

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

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

在构建第二个实例的过程中,当JVM耗尽堆时,可以释放第一个实例。

在一些罕见的情况下,显式空值有助于GC,其中以下所有情况都是正确的:

  • 变量是对象的唯一(非弱)引用
  • 您可以保证不再需要该对象
  • 变量将在范围内保留较长的一段时间(例如,它是长寿命对象实例中的一个字段)
  • 编译器无法证明对象已不再使用,但您可以通过对代码的高级逻辑分析来保证这一点:-)
在实践中,这在好的代码中是非常罕见的:如果不再需要对象,通常应该在更窄的范围内声明它。例如,如果仅在方法的单个调用期间需要该对象,则该对象应该是局部变量,而不是封闭对象中的字段

显式空值真正有用的一种情况是:如果使用空值来指示特定的状态,那么设置为空值有时是必要和有用的。Null本身是一个有用的值,原因如下:

  • 空检查速度非常快,因此检查空值的条件代码通常比许多备选方案(例如调用object.equals())更有效
  • 如果尝试取消引用,会立即得到NullPointerException。这很有用,因为这是一种很好的编码风格,可以帮助您捕获逻辑错误

关于“最终”部分的观点很好+1.然而,我知道有些程序员似乎会考虑将最终的代码添加为“Culle”代码!看看这个答案:有很多程序员都这么认为。这几乎是一个宗教观点。我喜欢任何让编写bug而不是代码更难的东西:-)比如可读性?正如我所说,这归结为一场宗教争论。没有真正的对与错,只有个人的意见和偏好。我不期望其他人改变他们的观点,我只是表达我的观点。我认为期末考试的可读性不是一个问题,但正如你们基本上说的,每个人都有自己的观点。(还有:-)通常意味着我在开玩笑)这是一个非常罕见的案例,但事实并非如此。虽然如果真的发生这种情况,我怀疑你在设计方面会有更大的问题。你确定在你减小大小后要
元素[size]==null吗?@AndrewLazarus看起来很正确。想象一堆大小为1的东西。它在
元素[0]
中存储了一个元素。元素缓存为结果,数组中的位置为空,导致堆栈大小为0。