值传递和引用传递区别是什么?

丘处机 / 2023-08-15 / 原文

先看两个例子,如果例子的背后原理都懂,就不需要看这篇文章了,如果看不懂其中的某一个,那么就听我道来~

 1 public class Demon02 {
 2     public static void main(String[] args) {
 3         int a =1;
 4         System.out.println(a);
 5         changeNumber(a);
 6         System.out.println(a);
 7     }
 8     private static int changeNumber(int a){
 9         a=10;
10         return a;
11     }
12 }

结果
1
1

 1 public class Demo01 {
 2     public static void main(String[] args) {
 3         Person person = new Person();
 4         System.out.println(person.name);
 5         changeName(person);
 6         System.out.println(person.name);
 7 
 8     }
 9     static class Person{
10         private String name;
11     }
12     private static void changeName(Person person){
13         person.name="张三";
14     }
15 
16 }

结果

null

张三

一般第二个例子比较好理解,因为将person这个对象的属性name赋值了张三,所以他的值会发生变化,第一个例子应该有不少人会懵圈。那为啥会出现这个结果呢?先看两个概念:

值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递:是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
先说例子1:
第5行代码调用了第8行的方法,其中第5行的a是实参,第8行的a是形参,调用的时候是将10这个值赋予方法中a的值,这样形参a第8行为1,接着第9行形参a的值被修改为10,第10行返回形参a的值10.
但是第5行并没有接收函数返回值。所以并没有改变第三行赋于a=1的值,这样第6行打印a的时候值还是1.
例子2:
第3行首先new了一个person对象,第5行调用方法的时候将person对象的地址已经传递到函数的形参person,此时对person对象的属性name赋值张三,那么同时修改了第3行建的person对象的属性name值。
所以第6行再次打印的时候,就会出现张三的名字。
那么我们对例子1做简单的调整,就会发现不一样的结果:
 1 public class Demon02 {
 2     public static void main(String[] args) {
 3         int a =1;
 4         System.out.println(a);
 5         a = changeNumber(a);
 6         System.out.println(a);
 7     }
 8     private static int changeNumber(int a){
 9         a=10;
10         return a;
11     }
12 }

第5行加一个a=之后结果如下:

1
10

那这又是为啥呢?

原因是将函数返回的值重新赋于a,这样修改了a的值,使得a=10.