Java值传递问题
结论:Java参数传递方式只有值传递。
问题:在实际开发中,我们会遇见调用函数时传递参数后,实际参数的值被调用的函数改变了,这时候我们会想,Java不是值传递吗?咋把我实际参数给改了呢?我们下面就来分析一下这些情况。
值传递和引用传递的概念
我们在分析问题之前先明确下这两种传递的概念:
- 值传递 :在调用函数时,将实际参数的值复制一份传递给函数,那么实际参数的值就不会被函数更改了;
- 引用传递:在调用函数时,将实际参数的引用,即地址传递给函数,函数操作的就是实际地址指向的源数据了,这样就会数据就会被更改了;
场景分析
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中拷贝的一份副本,还是算值传递,不必太纠结这个。简单区别下
拷贝实参副本传递给形参的:值传递;
没拷贝副本直接将实参地址传给形参的:引用传递。