【问题标题】:Set object reference to null or call the finalize() method?将对象引用设置为 null 或调用 finalize() 方法?
【发布时间】:2015-03-05 15:48:46
【问题描述】:

作为一个java初学者,我想问一下是否应该将对象引用设置为null,还是在大型项目中调用finalize方法?

例如,

while( obj... some code here){
 //code stuff
}
obj = null; // or obj.finalize();

既然我已经完成了obj 并且没有更多关于它的引用,我应该如何处理它?将其设置为 null 或调用 finalize();?

我读了java doc 但这段The finalize method is never invoked more than once by a Java virtual machine for any given object. 让我很困惑。这是否意味着即使我使用它,除非 GC 决定这样做,否则它根本不会做任何事情?那么,我将 obj 设置为 null 的决定会有帮助吗?

这一切都假设它是一个大型项目,并且范围尚未结束,以便 GC 自行释放它。谢谢。

【问题讨论】:

  • 这可能有助于理解finalize-方法和GC:stackoverflow.com/questions/2506488/…
  • 感谢您回复 wassgren,我已经按照说明阅读了 java 文档。但是有像this 这样的解决方案强制使用finallize 方法并且确实有效,我想知道你应该在一个大项目上做什么。
  • 永远不要使用 finalize 方法。这是完全不可预测的。

标签: java garbage-collection jvm


【解决方案1】:

两者都没有。如果obj 不再在代码中进一步使用(并且没有其他引用与obj 相同的对象),则该对象将不再可访问,并将成为垃圾收集的候选对象。

obj 设置为null 不会有任何效果(YMMV 取决于垃圾收集器的实现)。

至于拨打finalize(),不要。让垃圾收集器来处理。但请注意,finalize 是一种与其他方法一样的方法。您引用的文字是说,无论您的代码可能调用了多少次,GC 都不会多次调用它。

【讨论】:

  • 是的,但是 obj 是否有资格让 GC 在运行时选择,还是会等待 obj 被调用的方法的范围结束并决定?同样正如我在另一条评论中所写,是否值得强制使用 finallize 方法?如示例所述here
  • @VasilisCh 作为初学者,您不必担心。让自动 GC 处理它。它将检测对象何时不再使用并将其删除。使用完对象后停止引用它,一切都会自行解决。
  • @VasilisCh 不,范围是不同的概念,它定义了您可以在何处使用名称。处理 GC 资格的是可达性。
【解决方案2】:

切勿手动调用对象的finalize() 方法。它仅供 VM 使用。 VM 将在适当的时间调用它(作为垃圾收集过程的一部分)。

您可以将引用变量设置为null,以使对象能够比其他情况更早地进行垃圾回收,但这样做不会导致它立即被 GC。 (请注意,您使用 = 运算符进行赋值;== 是一个关系运算符,用于测试其操作数的相等性。)

如果您的对象保持您必须确保按需清理的状态,则为此实施不同的方法。 close() 是此类方法的流行名称。如果可能的话,最好避免实现finalize()。 GC 将自动处理您可能认为需要在 finalize() 中手动清理的大部分资源。

【讨论】:

  • 将覆盖该对象的 finalize 方法并调用它有什么不同吗?正如我在this 上阅读的答案,它考虑到了这一点,是真的吗?
  • 我重复一遍:从不手动调用对象的finalize() 方法。它是继承自 java.lang.Object 还是覆盖都没有区别。顺便说一句,您链接的答案非常好,并且与我所说的任何内容都没有任何矛盾。
  • @VasilisCh 不要覆盖finalize,除非你有很好的理由。此外,作为初学者,请忽略所有与 GC 相关的内容。它做得很好,你所做的任何事情都有可能使事情变得更糟。您需要关注的案例非常少见(例如,请参阅grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…),当您进行高级操作时,您可能会每月一次。
  • 感谢您回复@maaartinus,我只是对它很感兴趣,因为在 C++ 上我们必须解除分配和东西,因为 JVM 为我们做了这些,我想如果我知道的话,也许我可以提高性能一点更多关于垃圾收集器的信息。事实是我在我的一个摇摆项目上起步很低,但结果却一直在增长,因为我想给它添加越来越多的功能。所以我只是想知道,因为它已经超过 40k 行代码,如果我可以帮助提高性能。
  • @VasilisChados 不客气。 Java 非常不同。您必须关闭流并处理图形(使用try-finally 而不是依赖finalize,因为它不像析构函数;对于大多数用途来说,调用它为时已晚!),但您几乎不需要关心内存。使用 Swing,您需要在不再需要组件时取消注册侦听器。由于 JIT 编译器,Java 性能比 C++ 复杂得多。在优化之前,请确保您知道存在问题并仔细定位。
猜你喜欢
  • 1970-01-01
  • 2011-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多