java 传值 还是 传引用

前言

大家都知道,对于基本类型(int char float等等),java是传值。对于某个对象,java传递的是什么呢?

疑惑

最近刷 leetcode 删除链表一个节点的时候, 遇到这个问题

看下面代码


public class DeleteNodeLinkedList {
    public static void main(String[] args) {
        ListNode n0 = new ListNode(10);
        ListNode n1 = new ListNode(11);
        ListNode n2 = new ListNode(12);
        ListNode n3 = new ListNode(13);

        n0.next = n1;
        n1.next = n2;
        n2.next = n3;

        System.out.println("before delete in main " + n2);

        deleteNode(n2);

        System.out.println("after delete in main " + n2);

    }

    public static void deleteNode(ListNode node) {

        if (node == null) {
            return;
        }
        // the last node
        if (node.next == null) {
            node = null;
        }

        System.out.println("before assignment in deleteNode " + node);

        node = node.next; //这行代码影响很大

        System.out.println("after assignment in deleteNode " + node);
    }

}

class ListNode {
    int val;
    ListNode next;

    ListNode(int x) {
        val = x;
    }
}

在方法体deleteNode(ListNode node) 我们用node = node.next; 改变了node, 企图删除这个node

输出结果

before delete in main ListNode@27feae0f
before assignment in deleteNode ListNode@27feae0f
after assignment in deleteNode ListNode@41556f4c
after delete in main ListNode@27feae0f

令人遗憾的是, 从方法体内的 before assignmentbefore assignment 可以看出, 在方法体内部, node 是改变了

但是在mian函数里面, node 的值 before deleteafter delete是一样的

总结与反思

Note

java 是传值的,

对于对象类型,在方法体内部, 也是传递了一个引用的副本

这其实也不难理解, 比如说isSameTree(r0, r0) 我将一个对象作为a参数和b参数传进去, 如果都是同一个引用, 不是混乱了.

所以在方法体的内部是引用的副本,上文node = node.next;是引用的副本改变了,但是真实的引用被没有改变。所以方法里的改变并没有作用到main函数中。


当被传递给函数之后,一个对象至少存在两个引用

我们可以通过引用的副本改变这个实力的成员变量,但是改变这个实例本身只在方法内部起作用。

看下面这个例子


public class DeleteNodeLinkedList {
    public static void main(String[] args) {
        ListNode n0 = new ListNode(10);
        ListNode n1 = new ListNode(11);
        ListNode n2 = new ListNode(12);
        ListNode n3 = new ListNode(13);

        n0.next = n1;
        n1.next = n2;
        n2.next = n3;

        System.out.println("val before delete in main " + n2.val);

        deleteNode(n2);

        System.out.println("val after delete in main " + n2.val);

    }

    public static void deleteNode(ListNode node) {

        if (node == null) {
            return;
        }
        // the last node
        if (node.next == null) {
            node = null;
        }

        System.out.println("val before assignment in deleteNode " + node.val);

        node.val = node.next.val; //注意这行代码

        System.out.println("val after assignment in deleteNode " + node.val);

    }

}

class ListNode {
    int val;
    ListNode next;

    ListNode(int x) {
        val = x;
    }
}

这个我们在方法体内部改变的是对象成员变量的值, 发现是成功的

改变成员变量 输出

val before delete in main 12
val before assignment in deleteNode 12
val after assignment in deleteNode 13
val after delete in main 13

如果文章对你有帮助,还请多多支持 ^=^

支付宝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值