首页 > 解决方案 > 对象引用不影响它引用的对象?

问题描述

我对Java的理解是,如果你对同一个对象有两个引用,那么在一个引用下对对象状态所做的任何更改都会反映在另一个引用下。以两个 List 引用为例(为简单起见,省略了泛型)。

List list = Arrays.asList(1, 2, 3, 4, 5);
List list2 = list;
list2.set(0, 17);
System.out.println(list); //prints [17, 2, 3, 4, 5]

正如预测的那样,修改 list 的内容对 list2 具有相同的效果,因为它们都引用同一个 List 对象。但是,我在这里得到了意想不到的结果。

Node head = new Node(0);
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for(int number: numbers) head.appendToTail(number);
head.printNode(); //prints 0 1 2 3 4 5 6 7 8 9

Node target = head.next.next;
target = target.deleteNode(target, target.data);
head.printNode(); //prints 0 1 2 3 4 5 6 7 8 9

target 是对 head.next.next 中的 Node 对象的引用,因此删除它应该会消除 Node 2,但它没有。但是,将最后三行替换为以下代码。

head.next.next = head.next.next.deleteNode(head.next.next, head.next.next.data);
head.printNode(); //prints 0 1 3 4 5 6 7 8 9

当然,这要繁琐得多,所以我宁愿使用目标引用。为什么会这样?你可能不需要它,但为了以防万一,我会在下面包含我的 Node 类。

class Node {
    Node next = null;
    int data;

    public Node(int d) {
        data = d;
    }


    void printNode() {
        Node n = this;
        while (n != null) {
            System.out.print(n.data + " ");
            n = n.next;
        }
        System.out.println();
    }

    void appendToTail(int d) {
        Node end = new Node(d);
        Node n = this;
        while (n.next != null) {
            n = n.next;
        }
        n.next = end;
    }

    Node deleteNode(Node head, int d) {
        if (head == null) return null;

        Node n = head;

        if (n.data == d) {
            return head.next;
        }

        while (n.next != null) {
            if (n.next.data == d) {
                n.next = n.next.next;
                return head;
            }
            n = n.next;
        }
        return head;
    }
}

标签: javareference

解决方案


是的,它不会影响您的代码。

deleteNode在函数中考虑这个片段。

if (n.data == d) {
   return head.next;
}

考虑地址为 100 -> 200 -> 300 -> 400 -> 500 -> ...

所以,现在我们有,

Node target = head.next.next;

head节点现在指向地址 100。并target指向300。

在这之后,

target = target.deleteNode(target, target.data);

现在,if上面指出的条件被执行并target变为 400。没有实际删除发生。

现在,头节点仍然完好无损并打印整个列表。

例如,考虑以下内容。

target = target.deleteNode(target, target.next.data);
head.printNode(); //prints 0 1 2 4 5 6 7 8 9

因此,您的第一个节点删除逻辑确实删除了节点,但它只是返回了第二个节点。

如果要更改原始列表

head.next.next = target.deleteNode(target, target.data);
head.printNode(); // prints 0 1 3 4 5 6 7 8 9 

希望我澄清了这个问题。


推荐阅读