函数基本的参数传递机制有两种:值传递和引用传递。
值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实 参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。
引 用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来 的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
先来看个例子:
public class ValueTest {
public static void main(String[] args) {
new ValueTest().test();
new ValueTest().test2();
}
public void test(){
ChangeTest t1=new ChangeTest(3);
ChangeTest t2=new ChangeTest(5);
change(t1,t2);
System.out.println(t1.num);
}
public void test2(){
ChangeTest t=new ChangeTest(3);
change(t);
System.out.println(t.num);
}
public void change(ChangeTest source,ChangeTest dest){
source=dest;
System.out.println(source.num);
}
public void change(ChangeTest source){
source.num+=1;
}
class ChangeTest{
public ChangeTest(int value){
num=value;
}
public int num=0;
}
}
例子中输出结果为: 5 3 4
分析如下:
在函数public void change(ChangeTest source,ChangeTest dest) 中,source保存的是t1的副本,dest保存的是t2的副本。而t1是一个对象的地址,t1的副本也是一个对象的地址与t1指向同一个对象。source=dest只是把t2的副本赋给t1的副本,而t1的值并没有改变,在函数内部source指向的是t2的副本,所以source.num输出5;
而new ValueTest().test()中由于t1的值并没有改变所以t1.num输出3;
在函数public void change(ChangeTest source)中source.num+=1,是将 t 的副本指向的ChangeTest对象的值加1,也就是将t指向的ChangeTest对象的值加1,因为t的副本和t指向的是同一个对象,所以new ValueTest().test2()中t.num输出4。
经过以上分析我们得出结论:在Java中函数参数是按值传递的。