Java 的参数是值传递,不是引用传递
Java 中只有值传递,方法按值调用(call by value)。也就是说,方法得到的是所有参数值的一个拷贝,对拷贝的修改不会影响到参数值本身。基本数据类型参数引用存储的就是值本身,容易引起误解的是对象数据类型参数,通过下面两段代码示例做出说明。
基本数据类型参数
public static void main(String[] args) {
int num1 = 10;
int num2 = 20;
swap(num1, num2);
System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2);
}
public static void swap(int a, int b) {
// 参数 a、b 分别是 num1 、 num2 的拷贝
// 下面对拷贝的操作不会影响到原值
int temp = a;
a = b;
b = temp;
System.out.println("a = " + a); // 输出:a = 20
System.out.println("b = " + b); // 输出:a = 20
}
// 结果
a = 20
b = 10
num1 = 10
num2 = 20
对象数据类型参数
public static void main(String[] args) {
Employee a = new Employee("小明");
System.out.println(“a=” + a.getName()); // 输出:a=小明
print(a);
System.out.println(“a=” + a.getName()); // 输出:a=大明
set(a);
System.out.println(“a=” + a.getName()); // 输出:a=大明
}
private void print(Employee copy){
// copy 是虚拟机栈中 a 引用的一个拷贝
// 和 a 引用指向同一个堆内存中的实例对象
System.out.println("copy=" + copy.getName()); // 输出:copy=小明
// 此时通过拷贝修改的是堆内存中的实例对象状态
// 拷贝和参数引用仍然指向同一个实例对象
copy.setName("大明");
System.out.println("copy=" + copy.getName()); // 输出:copy=大明
}
private void set(Employee copy){
// 这里 copy 重新指向了新的 Employee 实例对象
// a 引用不受影响仍然指向原来的实例对象
copy = new Employee("小刚");
System.out.println("copy=" + copy.getName()); // 输出:copy=小刚
}
总结
- 方法不能修改基本数据类型的参数
- 方法不能修改对象类型的参数
- 方法得到的实际是参数引用的一个拷贝,即传递的是引用的值(容易误解为引用传递)
- 方法得到的参数引用拷贝和参数引用指向同一个堆内存中的实例对象
- 方法通过参数引用的拷贝也可以修改实例对象的状态
- 参数引用的拷贝可以重新指向堆内存中的一个新的实例对象,此时参数引用仍然指向原来的实例对象