Java里没有"引用传递"

来源:互联网 发布:在淘宝开店铺需要钱吗 编辑:程序博客网 时间:2024/04/30 16:37

以前,一直认为Java语言里方法的参数传递方法分为:值传递和引用传递。一直以来把形参为对象的引用变量的方法调用认为是"引用传递"。

 

但是,这一切都大错特错了。

 

在这里,我想说的是:Java里根本没有"引用传递",所谓的"引用传递"本质上仍然是"值传递"。

 

下面,用实例来证明我的结论:

public class MyTest {int num = 1;public void fun(MyTest mt) {mt = new MyTest();mt.num = 2;System.out.println("方法里对象的Field值:" + mt.num);}public static void main(String[] args) {MyTest mt = new MyTest();mt.fun(mt);System.out.println("方法外对象的Field值:" + mt.num);}}

 

打印结果为:

方法里对象的Field值:2
方法外对象的Field值:1

 

程序的执行过程如下图:

 

1.当程序执行MyTest mt = new MyTest();后,系统在堆内存中创建一个MyTest的对象,并且对象的num值初始为1。在main方法栈上,系统为引用变量mt分配栈空间,构造器将创建的MyTest对象以此对象的堆内存始地址返回并赋值给引用变量mt。至此,引用变量mt指向新创建的MyTest对象。

 

 

2.mt中保存的其实就是MyTest对象的地址,地址在计算机中也是二进制的0、1串呗。程序执行mt.fun(mt);系统做了些什么事情呢?第一:系统开辟了fun()方法的栈空间;第二:为fun()方法的形参mt分配栈空间;第三:将上图中新创建的MyTest对象的堆内存的首地址,也就是mt变量的值,复制一份(只不过这里复制的是一个地址罢了,本质还是值传递!)赋值给这个mt形参变量,此时,内存中的机制为:

 

 

3.当程序执行到方法fun()里的mt = new MyTest();mt.num = 2;之后,系统又创建了一个MyTest对象,并且让形参mt指向这个对象。如图:

4.fun()方法执行结束后,系统回收fun方法栈,形参mt不复存在。堆中在fun方法中实例化的对象在未来某个时刻将会被垃圾回收机制回收。

 

从上面得以看出:当调用方法fun之后,fun方法执行结束之前,系统中其实是存在两个mt变量的,只不过这两个mt变量曾经指向了相同的一片堆内存。在fun方法中执行

mt = new MyTest();的作用相当于改变形参mt的值,当fun方法执行结束之后,访问main方法中的mt所指向的对象发现:其num Field并未发生改变。这一点说明,fun方法的mt和main方法中的mt变量是两个独立的变量,他们占用着不同的内存区,而不是同一块内存。所以,Java中的看起来貌似"引用传递"的函数参数传递方法本质上也不过是"值传递",只不过这个传递的"值"是个"地址"罢了,好,地址是什么?计算机里不还是0、1串嘛,和一个变量本质上有任何区别吗?答:没有。 

 

到这里,结论显而易见了。