Java 徘徊和垃圾回收

9
我有一段代码用于Stack的pop方法,我正在尝试弄清楚它如何避免loitering(闲置)同时仍然返回我们索引当前指向的元素:
public String pop()
{ // Remove item from top of stack.
String item = a[--N];
a[N] = null; // Avoid loitering (see text).
if (N > 0 && N == a.length/4) resize(a.length/2);
return item;
}

从我的理解来看,我们正在将String对象的引用项指向数组a的索引元素(我们从最后一个元素开始使用其当前大小N-1,因此递减)。然后,如果我们返回引用,为什么在这样做之前要将引用所指向的索引元素设置为null?这不会使该项指向空并返回空吗?


Java中的引用总是被“复制”的,因此通过修改数组中的内容,您并没有改变从中获取的内容。 - Etienne de Martel
2个回答

19

只要对象还能被引用,就无法进行垃圾回收。如果您只是简单地使用--N更改索引但不将a[N]置为空,那么您将保留对该对象的引用,即使客户端代码不再引用该对象,也会防止其进行垃圾回收。

这是您需要在Java中将变量置为空的仅有的情况之一。

您似乎也误解了引用的含义。a[N]包含一个指向内存中对象的值。当您写String item = a[N]时,将该值复制到变量item中。现在,两个变量(itema[N])都指向同一对象。当您然后写a[N] = null时,从数组中删除该引用,但item仍包含指向原始对象的值。


啊,没错,a也是一个引用,但是指向数组对象。我明白了,谢谢。 - user2644819
所以你正在将数组的引用(我们对象的内存位置)复制到字符串对象的项引用中。现在,项指向数组对象。将我们的引用a设置为null是取消引用它,因为我们不再需要它了。问题:数组是否有多个引用,就像C++使用内存一样(每个索引指向内存中的某个空间)?因此,我们基本上只是取消引用其中的某个部分(以便垃圾收集器可以收集)? - user2644819
@user2644819 表示的不是指向数组对象的指针,它指向与 a[N] 相同的对象。这篇文章可能会让事情更清楚:https://dev59.com/EXVD5IYBdhLWcg3wQJOT - assylias
String[] a; a = new String[N];那么,引用a指向一个字符串对象吗?那么引用item也应该指向它,对吧? - user2644819
1
String[] a = new String[N] 中,a 包含一个指向对象的引用,该对象恰好是一个数组。每个数组项,例如 a[0],都包含一个指向字符串的引用。 - assylias
在这种情况下,我们如何摆脱item引用?! - razz

3

这个操作 复制 了数组中的引用,而不是引用数组成员本身。

 String item = a[--N];

现在您有两个对同一对象的引用,一个在本地变量中,另一个在数组中。这将删除数组中的副本:

 a[N] = null; // Avoid loitering (see text).

如果不从数组中移除它,将会继续存在一个不必要的引用,阻止垃圾回收。

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