在写值传递机制时先说一下形参和实参的区别
形参:定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。
实参:可以是常量、变量或表达式, 无论实参是何种类型的量,在进行函数调用时,都必须具有确定的值, 以便把这些值传送给形参。
对于形参来讲参数可以是基本的数据类型,如int,double,String这样的,也可以是抽象的类型,这一类一般我们叫它是引用数据类型,比如你写了一个Person类,那么你在写方法是可以这样来写void show(Person p),这相当于形参是Person这种类型的,只不过是一种抽象的类型而已。
下面我们通过一个交换两个整形值的例子来描述一下java的值传递机制
案例一:
public class ValueSwap {
public static void main(String args[])
{
int m=10;
int n=20;
ValueSwap v=new ValueSwap();
v.swap(m,n);
System.out.println("m:"+m+" "+"n:"+n);
}
void swap(int m,int n)
{
int temp=m;
m=n;
n=temp;
}
}
结果:
案例二:
public class SwapTest {
public static void main(String args[])
{
Data data=new Data();
data.m=10;
data.n=20;
SwapTest s=new SwapTest();
s.swap(data);
System.out.println("m:"+data.m);
System.out.println("n:"+data.n);
}
void swap(Data t)
{
int temp=t.m;
t.m=t.n;
t.n=temp;
}
}
class Data
{
int m;
int n;
}
结果:
在这两个例子中你可能会想为什么例一没有把两个数交换成功。而案例二就可以呢,其实在java中值传递是有相应的规则的:
1:如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
2:如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
在这里先附上例题一的内存图:
原因:从main方法进入程序,因为m,n都是局部变量所以要放在栈中,此时因为形参是基本数据类型,所以swap方法中m,n接收到的分别为具体值10,20.经过交换后swap方法中的m=20,n=10.看似这步已经成功了,其实swap方法执行完以后就会自动销毁从而从栈中弹出,从而m,n的值还是原来那样输出所以达不到我们预期的效果。
在看下例二的内存图:
原因:在main方法中我们new了一个data的对象在栈中,对于初始化的Data类的两个属性放在了堆中,此时data这个对象指向了堆空间的地址,由于java的swap(Data t)方法中的Data t是引用数据类型,所以实参传递来的是它的具体地址,此时相当于形参的指针也指向了m,n所在堆空间的地址,那么经过swap函数的操作,m和n的值也就交换了,此时虽然swap方法执行完毕从栈中弹出销毁了,但是Data的对象data还依然指向堆空间中m和n的值,此时变达到了我们的预期。