Queue dequeue()中的Java垃圾收集示例代码

Queue dequeue()中的Java垃圾收集示例代码,java,garbage-collection,Java,Garbage Collection,我在一门关于算法的课程中学习了队列实现的代码,并观察了作者使用的dequeue()代码: private Node first, last; private class Node { String item; Node next; } public boolean isEmpty() { return first == null; } // Code segment in doubt public String dequeue() { String item

我在一门关于算法的课程中学习了队列实现的代码,并观察了作者使用的dequeue()代码:

private Node first, last;

private class Node {
    String item;
    Node next;
}

public boolean isEmpty() {
    return first == null;
}

// Code segment in doubt
public String dequeue() {
    String item = first.item;
    first = first.next;
    if (isEmpty()) last = null;
    return item;
}
这里,first和last分别指向队列中的第一个和最后一个元素,这是可以理解的。我对作者使用的dequeue()中的代码有点怀疑。因为,他只是在做:

first = first.next;
未将first.next赋值为null。它会不会留下一个悬空引用(或游荡),这将阻碍JVM的垃圾收集机制?我有点困惑,dequeue()的代码应该是这样的吗?(我确信在C/C++中,代码应该如下所示,但我想知道在这种情况下JAVA的预期行为)


如果有人能给我指出一个详细介绍这个主题的资源,并提供一些很好的例子,我也将不胜感激。

设置
old.next=null
是不必要的,因为
old
已准备好进行垃圾收集(
first=first.next
分配消除了它最后一次的实时引用(一旦退出队列,垃圾收集器就不会跟踪它的任何引用。

假设队列中有两个对象:A和B

first
指向
A
first。next
指向
B
(换句话说
A.next==B

A
的唯一引用是
Queue#first
变量

first = first.next; // first == B

没有人再引用
对象,因此它有资格进行垃圾收集。

如果您的队列未实现为
双队列
(意味着您可以同时访问队列中的.Next和.Prev),然后将
first
设置为
first。next
,将不会有指向
first
的引用或指针,然后垃圾收集线程将知道它(
first
)需要进行垃圾收集(相关内存将被释放).

只有来自活动对象的引用才重要。这些引用确定哪些对象是活动的

如果一个对象有一个对活动对象的引用,但它没有被引用,则将收集该引用。(JVM不使用引用计数,并且不需要更新此计数)


另一种情况是,如果两个对象再次相互引用(但其他任何对象都不引用),那么这很好,因为只有可以从根节点(例如线程)访问的对象被保留,其他所有对象都被收集。

新的“第一个”后面的“old.next”的引用如何当“old.next”仍然引用“first”时,GC如何知道它必须对“old”进行垃圾收集?@sultan.of.swing垃圾收集器将忽略
old.next
引用,因为
old
不是活动的。收集器跟踪活动对象,因此如果
old
是活动的,那么它也将跟踪
old.next
引用;但是,
old
不是活动的(一旦
退出队列
退出),因此,它保留的引用并不重要。.@sultan.of.swing将堆中的所有对象都绘制成一棵树(实际上它们形成了一个图形,但树更容易可视化)。树的一个节点(“父”节点)指向两个“子”节点。删除“父”节点不必将父节点的“子节点”引用设置为null,因为当垃圾收集器遍历树时,它不会遍历“父节点”,因为您已将其从树中删除(因此它不可访问且不活动)我喜欢你把队列中的对象比喻成树,但是实际行为是什么,GC如何优化和知道所有的活引用?它是如何保持所有变量和当前引用的状态的?@ SultA.Of.Switter是一个好的开始的地方。最好的深度资源是C++。structor,但在Java中,old和first是对同一对象的引用。因此,您应该将this.first设置为null,这将使结构混乱,以便将来调用。但在原始实现中,first指向的原始对象不再具有对它的任何引用(假设队列只能向前遍历)。这使原始的第一个节点有资格进行垃圾收集。[旁白],不应
dequeue()
first call
isEmpty()
,否则,
字符串item=first.item
调用?@Kevin我想你是对的,必须测试一下空引用异常。我从幻灯片中逐字复制了代码。
first = first.next; // first == B