一、java中没有引用传递,全部是值传递。

java中方法调用参数传递类型无非两种,一种是基本数据类型、另一种是引用数据类型。受到这两种数据类型的影响,让人误以为,参数传递方式是和数据类型有关的,其实不然。无论是基本数据类型还是引用数据类型。下面我将分类阐述基本类型变量,与引用类型变量传递过程。

二、基本类型与引用类型内存模型介绍,以及基本数据类型传递过程

1、基本类型。

java 引用传值 java值传递与引用类型传递_引用传递


图一 执行结果为 :方法内部改变结果2

      改变最终结果1

  这里应该没有什么争执的地方。首先执行第7 行代码将会在栈中存储一个1的值。
在执行12行时 将会进行值传递 在图一中复制一个值为value --> 1

  所以在执行13行的value++ 的时候只是把 value --> 2 原来的 x–> 1 并没有任何改变。这个也证明了 基本数据类型的参数传递是值传递。

java 引用传值 java值传递与引用类型传递_引用传递_02


图二

2、引用类型。

对于引用类型是引用传递还是值传递,这个的争议比较大。如何证明引用数据类型也是值传递呢?
我们可以这样来证明。如下图。

java 引用传值 java值传递与引用类型传递_java 引用传值_03


图三   在这里将objA 设置为了null,但是在第十行的地方并没有出现空指针异常却正常的打印出了varA。原因如下图四所示在执行第七行的时候,在堆里面创造了一个VariableA()的对象。对象地址为0X1235H ,而栈里面是建立了一个objA ->指向0X1235H对象的记录。

  在执行地12行的时候在栈里面进行了值传递,传递的值为0X1235H 。在执行13行之后,堆栈情况如图五所示。obj的值变成了null 但是堆中和objA没有收到任何影响。所以在跳出changeValue的方法之后objA 仍然为0X1235。对应堆的对象也依然存在。所以不会出现空指针异常。

java 引用传值 java值传递与引用类型传递_内存_04


图四

java 引用传值 java值传递与引用类型传递_引用传递_05


图五

3,引用类型值传递特殊情况解释。

  像刚才上面提到,方法内部将对象置位null,并没有改变原来变量的对象。那么有些人可能会说不对啊,我在方法内部使用对象的getter.setter方法跳出子方法后,值的确是改变了啊?如下图6所示。

  我们可以看见值的确是改变了,那这一情况是不是与上面2所提到的相违背了呢?,其实并不是,这里要清楚一点,当我们对一个对象直接进行赋值 比如 objA = objB 、objA =null这样的操作我们可以认为他是发生在栈中的,只是改变了引用关系。堆中的对象并没有发生实质性的改变。

  那么不对一个对象直接进行赋值操作,而是通过圆点运算符操作类似于图六的第13行,或者是反射操作对象,或者直接操作public的属性,类似于 objA.age = 11 这样的操作。这样的操作在内存中发生了什么改变呢?他是当通过圆点运算符,可以理解为下一级操作,这样的话实际上通过栈中的内存地址访问到堆中的对象,使得其他引用该对象的变量也发生了变化。

java 引用传值 java值传递与引用类型传递_java_06


图六