Java值传递与引用传递的疑惑
在开始之前,先确定一下,Java只有值传递。
在之前的工作中,包括面试中经常听到有人说,在Java中,当基本类型数据在进行传递时是值传递,对象类型参数进行传递时是引用传递,并且会说的相当坚决,有时会让自己产生怀疑自己认知的感觉。
在说值传递和引用传递之前,我们先了解一些Java的基础知识:JVM 之 堆 / 栈
- 堆:用于存放对象实例和数组,线程共享;
- 栈:用于存储局部变量表,操作栈,动态链接,线程私有。
来几个例子:
基础数据类型:
对象类型:
emmmm,好像他们说的是有点道理,那再来看几个呢
String型:
对象类型:
啊,我去,这咋回事,我已经重新赋值了啊,怎么方法外部调用的值没有变。
我们来解释一下上面这个例子中的疑问
在开头我们提到了JVM的基础知识,我们知道了,new 的对象是在堆中创建的,方法中的局部变量,以及方法的参数列表是存储在栈中创建的,在我们调用change方法时,如果传递的时基础数据类型,那传的时具体的参数值(100),而传递的参数是对象类型时,那传递的是这个对象在堆中的内存地址值(0x00000001),看下面这一段代码:
其实,核心的点是,局部变量在栈中存贮的是对象的堆内存地址值,而且栈是有作用域的。
User param 和 User inputParam 是两个作用域中的局部变量,更改其中一个变量本身当然不会影响另一个,是更改变量本身哦,不是变量值对应的内存数据;
再看一个例子:
这个例子中,String是对象类型,然后在change方法内更改的也是变量本身,为什么外部调用的参数值没有被改变呢?
答:这是因为String其实是一个特殊的对象,并且String对象是不可变的,每次操作都是创建一个新的对象,所以上面示例中
inputParam = "change"; 等同于 inputParam = new String("change");