Java参数是pass by value还是pass by reference?两段代码结果为何不同
Java参数传递机制差异原因解析
首先明确核心规则:
Java 只有按值传递机制:
- 如果参数是基本类型,传递的是基本类型的字面量值的拷贝
- 如果参数是引用类型,传递的是引用所指向的对象在堆中的内存地址的拷贝,不是原引用变量本身,也不是对象本身
第一段Integer参数代码的逻辑说明
class Runner{ public static void main(String[] args) { Integer test = new Integer(20); updateObject(test); System.out.println(test); } public static void updateObject(Integer test) { test = 50; } }
输出为20的原因:
- Integer是不可变类,它内部存储数值的
value字段被final修饰,没有对外提供修改值的方法,任何修改Integer的操作实际都是创建新的Integer对象。 updateObject方法的参数test是main方法中test引用的地址拷贝,是方法内的局部变量。当执行test = 50时,会触发自动装箱,等价于test = Integer.valueOf(50),这一步是把方法内的局部test引用指向了新创建的数值为50的Integer对象,完全没有修改main方法中原test引用的指向,也没有修改原Integer对象的能力。- 方法执行结束后,局部变量销毁,main方法中的test还是指向原来数值为20的Integer对象,所以输出20。
第二段自定义类参数代码的逻辑说明
import java.util.*; class Test { int num; Test(int x){ num = x; } Test(){ num = 0; } } class Runner{ public static void main(String[] args) { Test test = new Test(20); updateObject(test); System.out.println(test.num); } public static void updateObject(Test test) { test.num = 50; } }
输出为50的原因:
updateObject方法的参数test同样是main方法中test引用的地址拷贝,两个引用指向堆内存中的同一个Test对象。- 方法内执行
test.num = 50时,并没有修改局部test引用的指向,而是顺着地址找到共同指向的Test对象,直接修改了它内部的公共属性num。 - 方法执行结束后,main方法中的test还是指向这个被修改了属性的Test对象,所以访问num属性得到的是修改后的50。
核心差异总结
- 第一段代码的操作是修改方法内局部引用的指向,让它指向新对象,不会对原引用和原对象产生任何影响
- 第二段代码的操作是通过局部引用访问共同指向的对象,修改对象的内部属性,原引用指向的还是这个对象,自然能看到修改结果
内容的提问来源于stack exchange,提问作者Ubuntu Learner
相关产品推荐
相关产品推荐

