首先我们知道,在Java中的方法是不能独立存在的,调用方法也必须使用类或者对象作为主调者。如果生命方法时包含了形参声明,则在调用方法时,必须给这些形参指定实参数值,调用方法时实际上传给形参的参数值就是实参。
那么在Java中到底实参是如何传入方法的呢?这是由Java方法的参数传输机制来控制的,Java里的方法参数传递为值传递,就是将实际参数的副本传入方法内,而实参本身不受任何影响。
对于8中基本类型我们通过下面的代码来测试一下:
public class PrimitiveTransferText {
public static void swap(int a ,int b) {
int temp = a;
a = b;
b = temp;
System.out.println("swap方法里的a的值为 "+ a +" b的值为: "+ b);
}
public static void main(String[] args) {
int a = 9;
int b = 6;
swap(a , b);
System.out.println("交换之后 "+ a +" b的值为 : "+ b);
}
}
结果:
swap方法里的a的值为 6 b的值为: 9
交换之后 9 b的值为 : 6
接下来我们通过画图来形象一点的展示参数传递的原理:
接下来我们通过代码演示引用类型的参数传递:
class DataWrap{
int a;
int b;
}
public class PrimitiveTransferText {
public static void swap(DataWrap dw) {
//下面三行代码实现dw的a b两个成员变量的值得交换
//定义一个临时变量来保存dw对象成员变量的值
int temp = dw.a ;
dw.a = dw.b;
dw.b = temp;
System.out.println("swap方法里的dw.a的值是 "+ dw.a +"dw.b的值是: " +dw.b);
}
public static void main(String[] args) {
DataWrap dw = new DataWrap();
dw.a = 9;
dw.b = 6;
swap(dw);
System.out.println("交换之后的dw.a的值是 "+ dw.a +"dw.b的值是: " +dw.b);
}
结果:
swap方法里的dw.a的值是 6dw.b的值是: 9
交换之后的dw.a的值是 6dw.b的值是: 9
下面我们同样通过画图形象的将原理展现出来:
对于引用类型,传入方法的参数虽然是实参的副本,但是由于对象是引用类型,它的复制同样在栈区开辟一块空间,指向实参指向的那块在堆中的内存,所以,他们指向的是同一块区域,a和b的值是相同的,无论是哪一个更改了堆中成员变量的值,两者的值都会改变,即都会收到影响,所以,引用类型的参数传递结果和数值类型的还是存在一定的差异,虽然他们的参数传递的原理是一样的。
下面通过代码测试一下交换两个对象类型的引用变量:
public static void swap(DataWrap dw1 ,DataWrap dw2) {
DataWrap temp = dw1;
dw1 = dw2;
dw2 = dw1;
System.out.println("swap方法里的dw1的值是 "+ dw1.toString() +"dw2的值是: " +dw2.toString());
}
public static void main(String[] args) {
DataWrap dw1 = new DataWrap(111,111);
DataWrap dw2 = new DataWrap(222,222);
swap(dw1,dw2);
System.out.println("交换之后的dw1的值是 "+ dw1.toString() +"dw2的值是: " +dw2.toString());
}
结果:
swap方法里的dw1的值是 DataWrap [a=222, b=222]dw2的值是: DataWrap [a=222, b=222]
交换之后的dw1的值是 DataWrap [a=111, b=111]dw2的值是: DataWrap [a=222, b=222]
我们接下来也画一下图:
解析一下,同样和前面的一样,传入方法中的是实参的拷贝,他们确实发生了交换,即他们指向堆中的内存地址发生了变化,但是内存中的数据并没有发生改变,所以,dw1和dw2依旧指向之前的内存地址,并且数值不变。