在每个应用程序中,在使用完对象后将其赋值为“null”

6
  • 在对象的作用域结束后,您是否总是将null分配给该对象?

  • 或者,您是否依赖JVM进行垃圾回收?

  • 无论应用程序的长度如何,您是否都这样做?

  • 如果是这样,这总是一个好的做法吗?


当你谈论JVM时,为什么要打C#的标签? - Sune Rievers
那个其他的标签是垃圾吗? - James Bloomer
那是一个错误。我只是想要编辑它。 - Sajal Dutta
1
顺便说一下,你可能想看看 java.lang.ref.WeakReference(和 java.lang.ref.SoftReference)。使用 WeakReferences,您可以保留对对象的引用,而不会阻止GC。 (因此,引用的对象随时可能消失) - sfussenegger
1
这可能是Java中最大的反模式。 - matt b
  1. 仅将null分配给对象并不会销毁它。它们毕竟在堆上,您仍然必须依赖JVM进行垃圾回收。
  2. 对象的作用域何时结束?如果您编写的代码使对象的作用域比需要的时间更长,则存在问题。
- pmr
14个回答

11

除非您有特定的理由,否则不需要明确将对象标记为 null。此外,我从未见过一款应用程序在不再需要时将所有对象标记为 null。垃圾收集的主要好处是内在的内存管理。


无论垃圾回收是否可用,你都必须担心。 - sfussenegger
2
我认为你对我的措辞过于字面了。 - Taylor Leese
我想表达的是,大多数情况下,标准的垃圾回收功能将会满足你的需求。 - Taylor Leese
2
我这么做只是为了取悦你,因为你对我的评论的理解并不是我想要表达的。 - Taylor Leese
除非你有非常特殊的原因,否则应该在赋值旁边加上注释! - Thorbjørn Ravn Andersen
显示剩余4条评论

8
  • 不要这样做,除非是特定情况,比如静态字段或者你知道一个变量/字段的生命周期比引用它的代码长很多
  • 可以这样做,但需要了解你的虚拟机限制(以及如何意外地保留内存块)
  • n/a

应该是“它引用的对象”而不是“引用它的代码(对象)”。一个对象可能在引用其他对象时被收集,但反过来则不行。 - sfussenegger
@sfussenegger:“一个对象可能在引用其他对象时被收集,但反过来不行。”那么循环引用呢? - Adamski
任何“根”无法访问的内容,无论是否循环,都有资格进行垃圾回收。 - TofuBeer
JVM曾经使用过各种垃圾回收算法。引用计数是最容易实现的算法,据我所知,在早期得到过应用,但在处理循环引用时受到了阻碍。更复杂且难以实现的算法可以确定某个对象是否无论如何都是可达的。 - David Thornley

6

我将几乎所有的变量声明为“final”。我还会让我的方法尽可能小,并将大多数变量声明为方法本地变量。

由于它们是final的,所以在使用后无法将它们赋值为空...但这没关系,因为方法很小,一旦返回对象就可以进行垃圾回收。由于大多数变量都是本地的,所以不太可能意外持有比需要更长时间的引用(内存泄漏)。


2

将 null 赋值给一个变量并不意味着它会立即被垃圾回收。实际上,它很可能不会被回收。通常而言,将变量设为 null 只是一种表面性的处理方式(静态变量除外)。


2

垃圾回收并不像你想象中的那样神奇。只要一个对象被任何可达对象引用,它就无法被回收。因此,为了避免内存泄漏,将一个引用设置为null可能是绝对必要的。我并不是说你总是应该这样做,但在必要时一定要这样做。


2
我们不会使用"null"来赋值。如果一个变量的作用域已经结束,它应该已经准备好进行垃圾回收了。可能有一些边缘情况,其中作用域由于长时间运行的操作而持续了更长的时间,在这种情况下将其设置为null可能是有意义的,但我想这种情况应该很少见。
此外,不用说,如果该变量是对象的成员变量或静态变量,因此永远不会真正离开作用域,则将其设置为 null 来进行垃圾回收是必需的。

1

我倾向于使用这种方法的情况是,如果我需要在方法的早期部分转换一个大型Collection

例如:

public void foo() {
  List<? extends Trade> trades = loadTrades();
  Map<Date, List<? extends Trade>> tradesByDate = groupTradesByDate(trades);
  trades = null; // trades no longer required.

  // Apply business logic to tradesByDate map.
}

显然,我可以通过重构成另一个方法来减少这种需要:Map<Date,List<? extends Trade>>> loadTradesAndGroupByDate(),所以这取决于情况/代码的清晰度。

1
上述代码可以简写为groupTradesByDate(loadTrades()),这样就不再需要该变量了。 - Kevin Panko
@Kevin - 同意。也许我把这个例子讲得太简单了 :-) - Adamski
你的观点仍然是正确的 - 有时这样做可能是有意义的。 - Kevin Panko

1

正如其他人所述,通常并不需要。

不仅如此,它还会使您的代码混乱,并增加了重新访问您的代码时某人需要阅读和理解的数据量。


1

赋值不是针对对象进行的,而是针对变量进行的,这意味着该变量随后将持有对某个对象的引用。将NULL赋给变量并不是销毁对象的方法,它只是清除一个引用。如果您要清除的变量在之后会离开其作用域,那么赋值NULL只是无用的噪音,因为这种情况在任何情况下都会在离开作用域时发生。


1

我只在以下情况下将引用分配给null

  1. 代码位于内存关键部分。
  2. 引用具有广泛的范围(并且必须稍后重复使用)。如果不是这种情况,我会在最小可能的代码块中声明它。它将自动可用于收集。

这意味着我仅在迭代过程中使用此技术,其中我使用引用来存储传入的大量对象集合。处理后,我不再需要该集合,但我想重用引用以获取下一个集合。

在这种情况下(仅在这种情况下),我会调用System.gc()来提示垃圾回收器。我通过堆可视化器监视了这种技术,并且对于大型集合(超过500Mb的数据)非常有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接