为什么说Java中只有值传递?

时间:2022-07-23
本文章向大家介绍为什么说Java中只有值传递?,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

重新定义什么是值传递和引用传递

相信我,当你正在看这篇文章的时,说明你对值传递和引用传递的理解大概率是错误的。如果你理解的是正确的,你应该也不会来看这篇文章。

在这里插入图片描述

正确的定义

  • 值传递:参数传递时,是拷贝实参的副本,然后传递给形参。
  • 引用传递:参数传递时,直接把对象的引用传给了形参。

你在问什么是实参,什么是形参对不对?对不对

形参与实参

  • 形参是指在定义函数时使用的参数,目的是用于接收调用该函数时传入的参数。简单理解,就是所有函数(即方法)的参数都是形参。
  • 实参,是指调用函数时,传递给函数的参数。
public static void main(String[] args) {
    int num = 3;
    printVal(num); //这里num是实参
}

private static void printVal(int num) {
    num = 5; //这里num就是形参
}

Java中调用方法传递一个参数的过程是怎样的?

当传递的参数是基本数据类型时

public class TestNum {
    public static void main(String[] args) {
        int num = 3;
        System.out.println("修改前的num值:"+num);
        changeValue(num);
        System.out.println("修改后的num值:"+num);
    }

    private static void changeValue(int num) {
        num = 5;
        System.out.println("形参num值:"+num);
    }
}

修改前的num值:3 形参num值:5

修改后的num值:3

你是不是觉得上诉例子是把num当成了实参传给了changeValue方法对不对?对不对?但你错了

真正的底层其实是把num拷贝了一个副本,然后把这个副本传给了changeValue

在这里插入图片描述

图中num是实参,然后创建了一个副本temp,把它传递个形参value,修改value值对实参num没有任何影响。

当传递的参数是引用类型时

public class User {
    private int age;
    private String name;
    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

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

    public User() {
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + ''' +
                '}';
    }
}
public class TestUser {
    public static void main(String[] args) {
        User user = new User(18, "zhangsan");
        System.out.println("修改对象前:"+user);
        changeUser(user);
        System.out.println("修改对象后:"+user);
    }

    private static void changeUser(User user) {
        user.setAge(20);
        user.setName("lisi");
    }
}

修改对象前:User{age=18, name='zhangsan'} 修改对象后:User{age=20, name='lisi'}

你是不是想说,这次总是引用传递了吧,毕竟对象都被改变了,对不对,对不对?但其实你又错了。文章一开始就说了,我们理解的引用传递其实并不是引用传递真正的定义。对象是被改变了,但这并不能代表引用传递,引用传递与我们传递的参数是不是原始变量有关,那么上诉例子的实际过程是下面这样的

在这里插入图片描述

user是对象的引用,为实参,然后创建一个副本temp,把它传递给形参user1。但是,他们实际操作的都是堆内存中的同一个User对象。因此,对象内容的修改也会体现到实参user上。那么也就是说,还是传递的是副本,并不是原始的对象的本身,所以还是值传递。

总结

与很多人一样,我也以为传递的是对象就是引用传递。但其实这一点是错误的。真正的引用传递并不是这样定义的,Java传递参数也并不像我们表面看到的那样简单。

参考:https://segmentfault.com/a/1190000021529503