哪个更快,直接分配变量还是保存温度?

Which is faster, assigning variable directly or saving temp?

所以我在阅读 java.util.LinkedList 的源代码时发现了一个让我感兴趣的设计选择。这是从 .clear() 方法中提取的,在该方法中,它们迭代地遍历链表中的每个元素,以将它们全部从内存中删除。我的问题是:为什么他们定义变量 next 而不是直接分配 x ?复制那个元素不需要时间吗?至少,在该范围内暂时需要更多space。

for (Node<E> x = first; x != null; ) {
    Node<E> next = x.next;
    x.item = null;
    x.next = null;
    x.prev = null;
    x = next;
}

这实际上是必需的。我将回顾一下算法和代码,以便向您展示为什么需要它。请注意,这个问题涵盖的主题很复杂,因此我的回答略有表述,以便对初学者更有意义。

首先,重要的是要了解当我们使用对象时 JVM 内部实际发生了什么。在 Java 中,一个对象(注意这不包括原始类型)在我们使用它们时实际上并没有被传递。相反,我们使用 references 对象,它们只是指向所述对象的指针。我们这样做是为了不用担心内存 allocation/de-allocation。现在,为了确保在我们不再需要某个对象时将其删除,所有对象都有一个计数,即在程序的当前状态下当前引用了多少次。从广义上讲,当进入使用某个对象的范围时,对象的引用计数在进入范围时递增,在离开范围时递减。现在,当一个对象达到 0 个引用时,这意味着当前我们的程序中没有使用该对象的部分,因此可以安全地删除它。这只是垃圾收集工作原理的简要总结,但最终要复杂得多。

此方法迭代遍历列表中的每个项目,解引用当前节点 x 的每个项目,也有参考。这并不是说对象 itemprevnext 应该设置为 null,只是x 对这些对象的引用。这样做是为了让我们知道当一个对象有 0 个引用时,我们可以安全地对该对象进行垃圾回收。如果我们按照您的建议去做,比如这里:

for (Node<E> x = first; x != null; ) {
    x.item = null;
    x.prev = null;
    x = x.next;
}

那么在我们赋值给x.next之前的节点x仍然保持着对[的引用=49=],这显然是不需要的,因为即使原始 x deleted/goes 超出范围,该对象仍将继续在内存中浮动。

要回答您关于哪个更快的问题,这无关紧要。是的,在那个范围内,我们为创建变量 next 节省了几个字节,但重要的是要了解我们只是在创建对它的引用,我们实际上并没有实例化一个新对象,因此几乎没有开销(并针对 JVM 进行了优化)。这个 next 对象只是临时分配在堆栈上,在下一次循环迭代时会覆盖它,因此它也不会产生任何内存使用问题。