值传递#

Java的方法参数传递是值传递!是值传递!值传递!!!重要的事情说三遍。

什么是值传递?

一个很简单的例子:

class MethodParaTest
{
private static void swap(int a,int b)
{
int temp;
temp = a;
a = b;
b = temp;
System.out.println("swap Method : a = "+a+" , b = "+b);
}
public static void main(String[] args)
{
int a = 1,b = 2;
swap(a,b);
System.out.println("New Value : a = "+a+" , b = "+b);
}
}

运行结果:

swap Method : a = 2b = 1

New Value : a = 1b = 2

可见,原值并未发生任何变化,这是因为在调用swap方法时,出入的参数是int变量a,b的值副本而非其本身,所以在swap方法中发生的一切事情在调用结束后对原变量并未产生任何影响,而形参a,b也在方法执行完毕后被销毁。

关于引用类型的参数传递#

引用类型的变量包括类、数组、接口。

所谓引用,可以想象C中的指针,在变量中之储存引用的地址,指向被引用的对象,这里的对象可以是类的实例、数组、接口。

而发生参数传递时,所传递的是变量值得副本,在这里就是地址的副本,即将堆区存放的对象的地址传递给形参。

一个简单的例子:

class ReferParaTest
{
private int a = 1;
private int b = 2;
private static void swap(ReferParaTest o)
{
int temp;
temp = o.a;
o.a = o.b;
o.b = temp;
}
public static void main(String[] args)
{
ReferParaTest o1 = new ReferParaTest();
swap(o1);
System.out.println("NEW VALUE : a = "+o1.a+" , b = "+o1.b);
}
}

运行结果

NEW VALUE : a = 2 , b = 1

o1对象的a,b成员变量成功互换,但这时发生的还是值传递而非引用传递,因为o1只是一个引用变量,系统复制了它的值,但并未复制ReferParaTest对象本身,形参o和实参o1指向堆区的同一对象,所以可对这一对象进行修改。

另一个例子

class ReferSwapTest
{
String s;
public ReferSwapTest(String s)
{
this.s = s;
}
public static void swap(ReferSwapTest a,ReferSwapTest b)
{
ReferSwapTest temp;
temp = a;
a = b;
b = temp;
}
public static void main(String[] args)
{
ReferSwapTest r1 = new ReferSwapTest("first");
ReferSwapTest r2 = new ReferSwapTest("second");
swap(r1,r2);
System.out.println("NEW VALUE : r1 = "+r1.s+" , r2 = "+r2.s);
}
}

运行结果

NEW VALUE : r1 = first , r2 = second

与第一个例子相同,对象并未发生任何变化,因为传递的依旧是r1,r2值得副本,而非对象本身,所以发生交换的只是形参a,b内所存储的值,与原变量无关。

需要注意的是:#

对于引用变量的参数传递,可以在调用的方法中对原对象进行修改,但原引用变量的指向值不发生变化,第二个例子中在swap方法中修改了对象中的a,b的值,第三个例子说明了此时仍然发生的是值传递。

一个形象但可能不太恰当的比喻:

一个变量是一座房子,变量的地址是房子的地址,变量的值是房子里面的家具和其他物品。

这样,这几种传递方式就成了这样,

值传递:去家具店买了一模一样的家具搬到新房子里,随便怎么折腾,老房子的家具不会发生任何变化,但如果把一张写有存放宝箱地址的纸条(引用变量)也抄录一份搬到新房子,那么通过这张纸条就可以找到宝箱再次折腾,这样宝箱里的宝物就可能变了。

引用传递:直接把自己的房子给人家折腾,当然会大变样。

指针传递:把自己房子的地址给人家,这样,人家通过地址还是可以找到你的房子,折腾不折腾的就看心情了。