Java值传递与引用传递的疑惑

在开始之前,先确定一下,Java只有值传递

在之前的工作中,包括面试中经常听到有人说,在Java中,当基本类型数据在进行传递时是值传递,对象类型参数进行传递时是引用传递,并且会说的相当坚决,有时会让自己产生怀疑自己认知的感觉。

在说值传递和引用传递之前,我们先了解一些Java的基础知识:JVM 之  /

  • 堆:用于存放对象实例和数组,线程共享;
  • 栈:用于存储局部变量表,操作栈,动态链接,线程私有。

来几个例子:

基础数据类型:

Java值传递与引用传递的疑惑

对象类型:

Java值传递与引用传递的疑惑

emmmm,好像他们说的是有点道理,那再来看几个呢

String型:

Java值传递与引用传递的疑惑

对象类型:

Java值传递与引用传递的疑惑

啊,我去,这咋回事,我已经重新赋值了啊,怎么方法外部调用的值没有变。

我们来解释一下上面这个例子中的疑问

在开头我们提到了JVM的基础知识,我们知道了,new 的对象是在中创建的,方法中的局部变量,以及方法的参数列表是存储在中创建的,在我们调用change方法时,如果传递的时基础数据类型,那传的时具体的参数值(100),而传递的参数是对象类型时,那传递的是这个对象在堆中的内存地址值(0x00000001),看下面这一段代码:

Java值传递与引用传递的疑惑

其实,核心的点是,局部变量在栈中存贮的是对象的堆内存地址值,而且栈是有作用域的。

User param 和 User inputParam 是两个作用域中的局部变量,更改其中一个变量本身当然不会影响另一个,是更改变量本身哦,不是变量值对应的内存数据;

再看一个例子:

Java值传递与引用传递的疑惑

这个例子中,String是对象类型,然后在change方法内更改的也是变量本身,为什么外部调用的参数值没有被改变呢?

答:这是因为String其实是一个特殊的对象,并且String对象是不可变的,每次操作都是创建一个新的对象,所以上面示例中

inputParam = "change"; 等同于 inputParam = new String("change");