java的值传递

想必大家都听说过一句话,“java只有值传递没有引用传递”,初学java 的时候对这句话有很多不解,就像下面这样

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static void main(String[] args) {
        Person xiaoming = new Person("xiaoming",18);
        Person zhangsan = new Person("zhangsan",24);
       
        zhangsan = xiaoming;
        System.out.println("张三的名字是" + zhangsan.getName() + ",年龄是" + zhangsan.getAge());

    }

上述代码应该输出张三的名字是xiaoming,年龄是18

你可能觉得,这不就是引用传递吗?

非也,让我们看下面一段代码

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static void main(String[] args) {
        Person xiaoming = new Person("xiaoming",18);
        Person zhangsan = new Person("zhangsan",24);
        Person lisi = new Person("lisi",30);
        zhangsan = xiaoming;
        xiaoming = lisi;
        lisi.setName("test");
        lisi.setAge(99);
        System.out.println("张三的名字是" + zhangsan.getName() + ",年龄是" + zhangsan.getAge());
        System.out.println("小明的名字是" + xiaoming.getName() + ",年龄是" + xiaoming.getAge());
    }

以上代码会输出什么呢?

张三的名字是xiaoming,年龄是18
小明的名字是test,年龄是99

是不是和想象中的不太一样?按照引用传递来说,最后经过引用传递xiaoming和zhangsan都应该指向的lisi呀,那最后答案应该都是test和99

其实这也就验证了java中并不存在引用传递,第一种代码带给我们一种java有引用传递的一种错觉。

实际上,java在传递引用类型参数的过程中传递的是目标的内存地址,而不是传递引用。为了帮助理解这两者的区别,我画一张图来解释一下,均为本人拙见,如有错误欢迎指出!

首先是引用传递

在这里插入图片描述

经过前面的代码操作以后,如果是引用传递应该变为下图这种状况

在这里插入图片描述

再来看值传递

在这里插入图片描述

经过上述变换,变为了下面这个样子

在这里插入图片描述

为什么呢,因为java值传递传递的是引用类型数据实例的地址,所以他们的指向变成了图上这种情况,这时修改lisi的数据会导致xiaoming的数据更改的原因并不是因为xiaoming指向了lisi,而是因为xiaoming指向了lisi的数据,因为lisi更改了内存中“李四,30”的数据,xiaoming又指向了这块内存,所以才会输出“小明的名字是test,年龄是99”。

关于值传递这里再多说一点比较具有代表性的场景

public void swap(int a, int b){
        int c = a;
        a = b;
        b = c;
    }

public static void main(String[] args) {
    int a = 1;
    int b = 2;
    swap(a,b);
    System.out.println("a=" + a + ",b=" + b);
}

这种情况下输出结果为a=1,b=2,因为java是值传递,传递进去的是a=1,b=2的副本,副本在函数中无论怎样操作都是影响不到原数据的

    public static void swap(Person a, Person b){
        Person c = a;
        a = b;
        b = c;
    }
public static void main(String[] args) {
        Person xiaoming = new Person("xiaoming",18);
        Person zhangsan = new Person("zhangsan",24);
       
        swap(xiaoming,zhangsan);

        System.out.println("小明的名字是" + xiaoming.getName() + ",年龄是" + xiaoming.getAge());
        System.out.println("张三的名字是" + zhangsan.getName() + ",年龄是" + zhangsan.getAge());
    }

输出的结果为小明的名字是xiaoming,年龄是18
张三的名字是zhangsan,年龄是24

这是因为我们改变的是函数中的a,b所指向的内存地址,所以对我们函数外的xiaoming,zhangsan是没有影响哒

    public static void change(Person a){
        a.setName("张三");
        a.setAge(100);
    }
    public static void main(String[] args) {
        Person xiaoming = new Person("xiaoming",18);
        change(xiaoming);
        System.out.println("小明的名字是" + xiaoming.getName() + ",年龄是" + xiaoming.getAge());
    }

输出的结果是小明的名字是张三,年龄是100!

这好像又打破了我们前面对于值传递的认知,不是说好的没有引用传递,函数内的副本影响不到原数据吗!

别急,我们来分析一下,此时函数内确实存在着副本a,但是经由值传递过后,a的地址指向指向了xiaoming的数据地址,那么这个时候我们去修改a的数据是不是就是修改xiaoming的数据地址内的数据呢?所以xiaoming最后的输出结果是“小明的名字是张三,年龄是100”,是不是很有意思

以上这就是我个人对于java值传递的一些思考,希望能对迷茫的你有一些帮助,本人拙见仅供参考并非一定正确,如有错误欢迎指正,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值