垃圾收集器与集合

Sva*_*.Mu 4 java garbage-collection

我已经阅读了几篇关于Java中垃圾收集的帖子,但我还是无法决定是否明确地清除一个集合被认为是一种好的做法......而且由于我找不到明确的答案,我决定在这里问一下.

考虑这个例子:

List<String> list = new LinkedList<>();
// here we use the list, perhaps adding hundreds of items in it...
// ...and now the work is done, the list is not needed anymore
list.clear();
list = null;
Run Code Online (Sandbox Code Playgroud)

从我在eg LinkedList或者的实现中看到的HashSet,该clear()方法基本上只循环给定集合中的所有项目,设置其所有元素(如果LinkedList还引用了next和previous元素)null

如果我做对了,设置listnull只删除一个引用list- 考虑到它是唯一的引用,垃圾收集器最终会处理它.我只是不知道在这种情况下,在垃圾收集器处理列表的元素之前还需要多长时间.

所以我的问题是 - 上面列出的示例代码的最后两行实际上是否有助于垃圾收集器更有效地工作(即更早地收集列表的元素),或者我只是让我的应用程序忙于"无关的任务"?

Joh*_*ica 9

最后两行没有帮助.

  • 一旦list变量超出范围*,如果这是对链表的最后一次引用,那么该列表就有资格进行垃圾收集.设置listnull立即事先没有任何价值.

  • 一旦列表符合垃圾收集的条件,如果列表仅包含对它们的引用,则执行其元素.清除列表是不必要的.

在大多数情况下,您可以信任垃圾收集器来完成其工作,而不需要"帮助"它.

*迂腐地说,它不是控制垃圾收集的范围,而是可达性.用一句话来总结可达性并不容易.有关此区别的说明,请参阅此问答.


此规则的一个常见例外是,如果您的代码保留的引用时间超过了所需的时间.这个典型的例子是听众.如果向某个组件添加侦听器,稍后不再需要该侦听器,则需要显式删除它.如果不这样做,那么该侦听器可以禁止自身及其引用的对象的垃圾收集.

假设我在一个按钮上添加了一个监听器:

button.addListener(event -> label.setText("clicked!"));
Run Code Online (Sandbox Code Playgroud)

然后在标签上删除,但按钮仍然存在.

window.removeChild(label);
Run Code Online (Sandbox Code Playgroud)

这是一个问题,因为按钮具有对侦听器的引用,并且侦听器具有对标签的引用.标签不能被垃圾收集,即使它在屏幕上不再可见.

现在是采取行动并加强GC良好一面的时候了.我添加它时需要记住听众...

Listener listener = event -> label.setText("clicked!");
button.addListener(listener);
Run Code Online (Sandbox Code Playgroud)

...这样我就可以在完成标签后删除它:

window.removeChild(label);
button.removeListener(listener);
Run Code Online (Sandbox Code Playgroud)