0%

JAVA只有传值调用(call by value)

前言

目前程序设计语言中有关将参数传递给函数调用有两种方法,按值传递(call by value)和按引用传递(call by reference)(C语言中可以通过指针直接传递地址,和传引用效果类似)。因为我之前是学C++的,所以想当然认为JAVA也有这两种参数传递方式。

可是看书之后才知道Java里只有传值调用,即在调用函数时,传递给形参的永远都是实参的副本,无论形参是基本数据类型(int,boolean)还是对象。

假设如果Java传递对象是按引用传递的,那么下列代码的结果应该是b,a。可是实际结果还是a,b,说明swap函数没有成功交换两个对象。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Employee{
private String name;
public Employee(String name){
this.name = name;
}
public void getName(){
System.out.println(this.name);
}
}

public class Study {
public static void swap(Employee x, Employee y){
Employee tmp;
tmp = x;
x = y;
y = tmp;
}
public static void main(String[] args) {
Employee a = new Employee("a");
Employee b = new Employee("b");
swap(a,b);
a.getName();
b.getName();
}
}

疑问

但是如果按值调用,为什么能修改传入函数中对象的属性呢?

如果之前有C/C++基础,从指针角度理解,很容易就想通了。a、b为实参,x、y为形参,当调用swap()是,你可以理解Java新生成了a的值,并且将其赋值给了x,y亦然。然后这四个变量相当于四个指针,他们分别指向两块堆内存空间,如果修改对象属性,那么通过这个指向关系,通过成功修改堆内存空间里的内容,如果想交换对象,那么在函数内交换的只是形参的指向关系(如红色箭头所示),并不会影响到a、b对象的指向关系。

总结

Java只有传值调用,函数调用不能修改基本数据类型参数的内容,可以修改对象参数的属性内容,不能修改对象参数的指向关系,即不能让对象参数引用到别的对象上去。