Java中变量与数组元素的传值与传引用差异解惑
这是个非常经典的困惑点,很多刚接触Java的开发者都会被这个问题绕进去——其实核心只有一句话:Java里所有参数传递都是按值传递,没有按引用传递这回事!我们来拆解你给出的两个例子,就能明白背后的逻辑:
例子1:基本类型(int)的参数传递
先看你的代码:
public class MyClass { public static void test(int a, int b) { System.out.println("In test() at start: "+a+" "+b); int temp=a; a=b; b=temp; System.out.println("In test() at end: "+a+" "+b); } public static void main(String args[]) { int a=1, b=2; System.out.println("a: "+a+" b: "+b); test(a, b); System.out.println("a: "+a+" b: "+b); } }
运行输出:
a: 1 b: 2
In test() at start: 1 2
In test() at end: 2 1
a: 1 b: 2
解释:
当你在main里调用test(a, b)时,传递的是a和b的值的副本——也就是说,test方法里的a和b是完全独立于main里的两个局部变量,它们只是一开始和原始变量的值相同。你在test里交换这两个变量,只是修改了副本的值,和main里的原始变量没有任何关系,所以main里的a和b始终是1和2。
例子2:引用类型(数组)的参数传递
再看第二个代码片段:
public class MyClass { public static void test(int[] arr) { System.out.println(arr[2]); arr[2]=20; System.out.println(arr[2]); } public static void main(String args[]) { int[] arr={0,1,2,3,4,5}; System.out.println(arr[2]); test(arr); System.out.println(arr[2]); } }
运行输出:
2
2
20
20
解释:
数组属于引用类型,main里的arr变量存储的并不是数组本身,而是一个指向堆内存中数组对象的引用(地址)。当你调用test(arr)时,传递的是这个引用的副本——也就是说,test方法里的arr参数和main里的arr变量,现在指向的是同一个堆内存里的数组对象。
所以当你在test里执行arr[2] = 20时,其实是通过这个引用副本,去操作它指向的那个数组对象,修改的是数组对象本身的内容。而main里的arr引用同样指向这个数组,所以自然能看到修改后的结果。
这里要注意一个关键区别:如果在test方法里给arr重新赋值,比如:
public static void test(int[] arr) { arr = new int[]{10,20,30}; // 给引用副本重新赋值 }
那main里的arr不会有任何变化——因为你只是修改了test方法里的引用副本的指向,让它指向了一个新的数组,而main里的原始引用还是指向原来的数组。
总结
- 对于基本类型:传递的是值的副本,方法内修改副本不会影响原始变量;
- 对于引用类型:传递的是引用的副本,方法内可以通过这个副本修改引用指向的对象内容,但无法修改原始引用的指向。
本质上,Java的参数传递都是按值传递——区别只在于,基本类型传递的是“值本身”,引用类型传递的是“引用的地址值”。
内容的提问来源于stack exchange,提问作者user9221677

