【问题标题】:Java pass by reference with listNode issueJava 通过引用传递 listNode 问题
【发布时间】:2018-02-13 22:58:06
【问题描述】:

我有一堂课:

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);

如果我做一个:

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); 时头部会改变我认为快速不是用头部分配的吗?

【问题讨论】:

  • head 仍然引用同一个对象。在 A 中,您让 fast 引用与 head 相同的实例,然后将该引用更改为下一个节点,同时保持引用 head 不变。 Java 是按值传递的,因为引用的“值”被复制和传递(不是引用的地址或指向引用的指针)。将 Java 引用视为某种指针:fast = head 表示您有两个“指针”指向同一个地址(它们具有相同的值),当您执行 fast = xxx 时,您让 fast 指向其他地址(您只更改该指针的值)。

标签: java assign


【解决方案1】:

当你分配一个变量时,你让它指向(引用)一个特定的对象。当你重新分配它时,你让它指向(引用)另一个对象,你不会覆盖它所持有的引用值:

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

为了更容易理解:

假设我们有 abc 类型为 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.

【讨论】:

  • 嗨,我已经编辑了我的问题并添加了一个案例,你能解释一下 C 吗?非常感谢。
  • 太棒了,在我弄乱 ListNode 指针并分配之前。这个解释让我现在清楚了。
【解决方案2】:

好问题,我也搞砸了 ListNode 引用/分配。

试试下面的用例,这将有助于你理解它。此示例可以提供与 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);

【讨论】:

    猜你喜欢
    • 2015-08-09
    • 2011-03-14
    • 2012-03-13
    • 2011-05-02
    • 2012-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多