Java值传递问题

结论:Java参数传递方式只有值传递。
问题:在实际开发中,我们会遇见调用函数时传递参数后,实际参数的值被调用的函数改变了,这时候我们会想,Java不是值传递吗?咋把我实际参数给改了呢?我们下面就来分析一下这些情况。

值传递和引用传递的概念

我们在分析问题之前先明确下这两种传递的概念:

  1. 值传递 :在调用函数时,将实际参数的值复制一份传递给函数,那么实际参数的值就不会被函数更改了;
  2. 引用传递:在调用函数时,将实际参数的引用,即地址传递给函数,函数操作的就是实际地址指向的源数据了,这样就会数据就会被更改了;

场景分析

1.基本数据类型

class Solution {
    public static void test(int a) {
      a = 20;
    }

    public static void main(String[] args) {
        int a = 10;
        test(a);
        System.out.println("a = " + a);
    }
}

运行结果:

a = 10

可以看出实际参数的值没有被改变。

2.引用类型:类,数组等

2.1
class Solution {
    public static void test(User user) {
      user.setUserName("update");
    }

    public static void main(String[] args) {
        User user = new User();
        user.setUserId(00001L);
        user.setUserName("test");
        test(user);
        System.out.println("User name is " + user.getUserName());
    }
}

运行结果

User name is update

可以看出实际参数已经被改变了!

根据上面两个例子我们已经可以得出一个小结论了,基本数据类型传递的是值,实参不会改变,对象传递的是引用,可能会被改变。那么是不是和Java只有值传递这个结论冲突了呢?
== NO!有个误区,不要认为传递的值就是值传递,传递的引用就是引用传递(地瓜不是瓜) ==

Java传递参数时都会从栈中拷贝一份实参的副本,栈中存放的是什么?我们知道栈中存放了局部变量表,表中存放基本数据类型、对象引用等。那么对于基本数据类型拷贝的就是数据,引用类型拷贝的就是对象引用,对象引用是指向具体对象的地址,所以在调用函数时函数操作的和实参指向的是同一个对象,所以实参会被更改。

2.2 String类型本身就是final类型,不会像其它引用类型被修改。

最后回到引用传递的定义

引用传递实参和形参指向同一块内存地址,Java中拷贝的一份副本,还是算值传递,不必太纠结这个。简单区别下
拷贝实参副本传递给形参的:值传递;
没拷贝副本直接将实参地址传给形参的:引用传递。