Java 通过引用传递 listNode 问题
Java pass by reference with listNode issue
我有一个 class:
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
打印LinkedList的函数是:
public static void printLinkedNode(ListNode l){
while(l != null){
System.out.print(l.val+" ");
l = l.next;
}
System.out.println(" ");
}
在我的主函数中,我创建了一个名为 test 的 ListNode:
ListNode test = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
如果我做 A:
ListNode fast = head, slow = head;
fast = fast.next.next;
printLinkedNode(head); // I get 1->2->3->4
如果我做 B:
ListNode fast = head, slow = head;
fast.next = fast.next.next;
printLinkedNode(head); // I get 1->3->4
我很困惑,为什么在A中,头部是1->2->3->4,而不是3->4?我已经阅读了一些关于 Is Java “pass-by-reference” or “pass-by-value”? 的帖子,但仍然无法弄清楚..
如果我做 C:
ListNode fast = head, slow = head;
fast = fast.next.next;
printLinkedNode(fast); //3->4
printLinkedNode(head); //1->2->3->4
fast.next = new ListNode(5);
printLinkedNode(fast); //3->5
printLinkedNode(head); //1->2->3->5, why the head will change?
我很困惑为什么当我们这样做时头部会改变 fast.next = new ListNode(5);我觉得 fast 不是用 head 赋值?
当您分配一个变量时,您使它指向(引用)一个特定的对象。当你重新分配它时,你让它指向(引用)另一个对象,你不会覆盖它持有的引用值:
ListNode fast = head, slow = head; // fast has a reference to head.
fast = fast.next.next; // fast has a reference to fast.next.next. You are not overwriting head, just fast.
printLinkedNode(head); // I get 1->2->3->4
相反,如果您编辑引用对象内部的内容,您将编辑原始对象:
ListNode fast = head, slow = head; // fast has a reference to head
fast.next = fast.next.next; // by editing fast.next, you edit head.next
printLinkedNode(head); // I get 1->3->4
用例 C 的更新:
ListNode fast = head, slow = head; // fast = head = (1)
fast = fast.next.next; // fast = fast.next.next = (3). head is still (1)
printLinkedNode(fast); // 3->4 -> because fast points to head.next.next (3)
printLinkedNode(head); // 1->2->3->4 -> head wasn't modified by any of the previous instructions
// here fast points to head.next.next. So fast.next is the same as head.next.next.next (4).
fast.next = new ListNode(5); // Overwrites fast.next, it was (4), becomes (5)
printLinkedNode(fast); // 3->5
printLinkedNode(head); // 1->2->3->5
为了更容易理解:
假设我们有 a
、b
和 c
类型的对象 ListNode
:
ListNode a = new ListNode(1);
ListNode b = new ListNode(2);
ListNode c = new ListNode(3);
ListNode d = a; // variable d now points to object a
d.next = b; // since d points to a, this statement modifies a.next
d = c // This does *not* modify a. It just makes d point to c.
好问题,我也搞砸了 ListNode reference/assigning。
尝试以下用例,这将有助于您理解它。此示例可以提供与 ListNode 的比较。
List<Integer> listA = new ArrayList<>();
listA.add(20);
List<Integer> listB = new ArrayList<>();
listB.add(30);
System.out.println("listA: " + listA);
System.out.println("listB: " + listB);
// assign list and it has a reference to listA
List<Integer> list = listA;
// re-assign list and it has a reference to listB now
list = listB;
/* modify list, listB will be changed too. Similar in ListNode class, e.g. ListNode dummy = head;
if you do dummy.next = ListNodeC or dummy.val = xxx, head's pointer and value will be changed too. */
list.add(88);
// you could see here listA is not changed since we have re-assign it with listB, now it points to listB.
System.out.println("listA: " + listA);
System.out.println("listB: " + listB);
System.out.println("list: " + list);
我有一个 class:
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
打印LinkedList的函数是:
public static void printLinkedNode(ListNode l){
while(l != null){
System.out.print(l.val+" ");
l = l.next;
}
System.out.println(" ");
}
在我的主函数中,我创建了一个名为 test 的 ListNode:
ListNode test = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
如果我做 A:
ListNode fast = head, slow = head;
fast = fast.next.next;
printLinkedNode(head); // I get 1->2->3->4
如果我做 B:
ListNode fast = head, slow = head;
fast.next = fast.next.next;
printLinkedNode(head); // I get 1->3->4
我很困惑,为什么在A中,头部是1->2->3->4,而不是3->4?我已经阅读了一些关于 Is Java “pass-by-reference” or “pass-by-value”? 的帖子,但仍然无法弄清楚..
如果我做 C:
ListNode fast = head, slow = head;
fast = fast.next.next;
printLinkedNode(fast); //3->4
printLinkedNode(head); //1->2->3->4
fast.next = new ListNode(5);
printLinkedNode(fast); //3->5
printLinkedNode(head); //1->2->3->5, why the head will change?
我很困惑为什么当我们这样做时头部会改变 fast.next = new ListNode(5);我觉得 fast 不是用 head 赋值?
当您分配一个变量时,您使它指向(引用)一个特定的对象。当你重新分配它时,你让它指向(引用)另一个对象,你不会覆盖它持有的引用值:
ListNode fast = head, slow = head; // fast has a reference to head.
fast = fast.next.next; // fast has a reference to fast.next.next. You are not overwriting head, just fast.
printLinkedNode(head); // I get 1->2->3->4
相反,如果您编辑引用对象内部的内容,您将编辑原始对象:
ListNode fast = head, slow = head; // fast has a reference to head
fast.next = fast.next.next; // by editing fast.next, you edit head.next
printLinkedNode(head); // I get 1->3->4
用例 C 的更新:
ListNode fast = head, slow = head; // fast = head = (1)
fast = fast.next.next; // fast = fast.next.next = (3). head is still (1)
printLinkedNode(fast); // 3->4 -> because fast points to head.next.next (3)
printLinkedNode(head); // 1->2->3->4 -> head wasn't modified by any of the previous instructions
// here fast points to head.next.next. So fast.next is the same as head.next.next.next (4).
fast.next = new ListNode(5); // Overwrites fast.next, it was (4), becomes (5)
printLinkedNode(fast); // 3->5
printLinkedNode(head); // 1->2->3->5
为了更容易理解:
假设我们有 a
、b
和 c
类型的对象 ListNode
:
ListNode a = new ListNode(1);
ListNode b = new ListNode(2);
ListNode c = new ListNode(3);
ListNode d = a; // variable d now points to object a
d.next = b; // since d points to a, this statement modifies a.next
d = c // This does *not* modify a. It just makes d point to c.
好问题,我也搞砸了 ListNode reference/assigning。
尝试以下用例,这将有助于您理解它。此示例可以提供与 ListNode 的比较。
List<Integer> listA = new ArrayList<>();
listA.add(20);
List<Integer> listB = new ArrayList<>();
listB.add(30);
System.out.println("listA: " + listA);
System.out.println("listB: " + listB);
// assign list and it has a reference to listA
List<Integer> list = listA;
// re-assign list and it has a reference to listB now
list = listB;
/* modify list, listB will be changed too. Similar in ListNode class, e.g. ListNode dummy = head;
if you do dummy.next = ListNodeC or dummy.val = xxx, head's pointer and value will be changed too. */
list.add(88);
// you could see here listA is not changed since we have re-assign it with listB, now it points to listB.
System.out.println("listA: " + listA);
System.out.println("listB: " + listB);
System.out.println("list: " + list);