链表引用工作机制解析:节点变化后temp为何仍指向初始节点?
问题解答
代码示例
public class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } public static void main(String[] args) { ListNode temp = new ListNode(0); ListNode current = temp; for(int i = 1; i < 10 ; i++ ) { current.next = new ListNode(i); current = current.next; } System.out.println(current.val); // output : 9 System.out.println(temp.next.val); // output : 1 System.out.println(temp.next.next.val); // output : 2 } }
问题1:当被引用的链表节点值发生变化时,链表中的引用是如何工作的?
Java里的对象引用本质是指向堆内存中对象实例的地址指针,不是直接存储对象的值。
- 当你通过一个引用修改节点的
val属性时,是直接修改堆里对应节点实例的数据。所有指向该节点的引用,访问val时都会拿到修改后的值——因为它们指向的是同一个对象实例。 - 举个简单例子:
这里ListNode nodeA = new ListNode(5); ListNode nodeB = nodeA; nodeA.val = 10; System.out.println(nodeB.val); // 输出10nodeA和nodeB指向堆里同一个节点,修改nodeA.val等于修改了这个节点本身的数据,nodeB自然能看到变化。
问题2:为何循环中current节点不断变化的情况下,temp仍然指向最初的current节点?
核心是引用变量的赋值和引用指向的修改是两回事:
- 初始时
ListNode current = temp;,是把temp存储的地址(指向堆里val=0的节点)复制给current,此时两者指向同一个节点。 - 循环里的
current = current.next;,是修改current这个变量本身存储的地址——让它指向当前节点的next引用对应的新节点(也就是每次循环创建的new ListNode(i))。但这个操作完全不会影响temp变量存储的地址,temp自始至终都指向最开始创建的那个val=0的节点。
打个比方:你和朋友各拿一张写着同一栋房子地址的纸条(temp和current初始状态),之后你把自己纸条上的地址改成了这栋房子隔壁的新地址(current = current.next),但朋友手里的纸条还是原来的地址,所以朋友找的始终是最初那栋房子,而你找的是不断更新的隔壁房子。
内容的提问来源于stack exchange,提问作者khalil ben khoud
相关产品推荐
相关产品推荐

