在初学Java的过程中有时候会出现一些看起来“不合常理”的结果,例如:
public static void main(String[] args){
int a = 10;
int b = 20;
method(a,b);
system.out.print(a,b);
}
public static void method(int c,int d){
int temp = c;
c=d;
d=temp;
}
此时运行输出的值,发现还是a=10,b=20,并没有发生转换。要理解这个问题就要了解Java中参数传递的机制。首先说明:JVM中有堆和栈两大内存空间,其中栈负责存放局部变量和方法,堆负责存放成员变量和类。
在参数传递中存在着数据值传递和地址值传递,基本数据类型传递数据值,而引用数据类型传递地址值。以上例来说,当main()方法调用method方法时,在栈中开辟method方法空间,其中实参a,b的数据值传递给形参c,d,然后这个方法完成转换后,方法结束,这个方法也被栈抛出。问题来了,栈中本身的a,b并没有发生任何变化,变化的只是在方法method中的c,d参数,而且在方法结束后这些参数随着方法一起被栈给抛出了,我们输出的是a,b的值,所以没有任何变化。这就是值传递。
那么,引用类型参数的传递机制是怎样的呢?
public class Test2 {
public static void main(String[] args) {
Student student = new Student();
student.id = 5;
getID(student);
System.out.println(student.id);
}
public static void getID(Student s){
s.id = 1001;
}
}
class Student{
int id;
}
如上所示,运行结果为1001.为什么这次就能修改成功了呢?这就是引用数据类型了。在栈中,student存放的是一段地址值,指向堆中新开辟的Student类空间存储数据,其中有成员属性id,默认为0.接着由student.id = 5将id值改为5.调用方法getID后,栈中开辟一个getID方法,student传递给形参s的为存储数据的地址值,指向同一个堆中的类空间对象,在方法中将student.id改为1001,接着方法结束,栈抛出,此时堆中的id值已经被方法修改过了,所以再输出student.id就是1001.
总之,如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值;如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。