首先了解在程序设计语言中,有关将参数传递给方法的一些专业术语:
按值调用(call by value)表示方法接收的是调用者提供的值。而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。
来看两个简单的例子:
public static void main(String[] args) {
int a = 10;
int b = 5;
swap( a , b);
System.out.println("a = " + a + " b = " + b); // result : a = 10 b = 5
}
public static void swap(int a , int b) {
int temp = a;
a = b;
b = temp;
}
这是一个简单的交换的例子,这个例子可以说明在基本的数据类型int中,将a , b 值作为形参传递给方法swap后,二者的值并未发生变化,说明这是值传递,因为对于swap方法而言,它是对于a,b的两个副本(拷贝值)进行操作,无法改变原始对象。
如果说是按照引用传递,方法接收的会是变量地址,它会修改传递引用所对应的变量值,那么最终打印出来的是"a = 5 b = 10"这与我们得到的结果是相违背的。
说到这里,或许有很多人会开始反驳我了,这只是基本数据类型,也没有说一定就很全,或者举出如下的例子来进行反驳。
public class Student {
private String id;
private String name;
private String grade;
public Student() {
}
public Student(String id, String name, String grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", grade='" + grade + '\'' +
'}';
}
}
public static void main(String[] args) {
Student student = new Student("0" , "张三" , "大三");
System.out.println(student.toString()); //result Student{id='0', name='张三', grade='大三'}
pass(student);
System.out.println(student.toString()); //result Student{id='1', name='lisi', grade='大三'}
}
public static void pass(Student passStudent) {
passStudent.setId("1");
passStudent.setName("lisi");
}
这个时候,在pass方法中确实改变了student对象,输出结果也发生了改变。但是这是不是引用传递呢?我们应该来看看整个过程中到底发生了什么:
在main方法中,运行到 Student student = new Student("0" , "张三" , "大三");
的时候,在堆上开辟了一个空间用来存储student对象的id,name,grade等数据(由于grade没变就不演示),当student作为实际参数传递给形参passStudent的时候,其实是传递student的地址0x112233
的拷贝交给了passStudent,所以此时操作相当于是直接在操作我们创建的student对象,这个时候谈到传递,确实是传递了0x112233的拷贝值,但是并未对这个拷贝值进行修改,而是对地址中存储的内容进行修改。所以看上去像是引用对象的发生了改变。
所以Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用