java只有值传递,基本类型传数值副本,引用类型传地址副本;因此可修改对象内容但不能改变原始引用指向。

Java 中只有值传递,这一点是确定无疑的。关键在于理解“值”到底指什么——对基本类型,是数据本身的副本;对引用类型,是对象地址的副本。所谓“能改内容但不能改引用”,正是这个机制的自然结果,不是特例,而是统一逻辑的体现。
经典三连问:看清形参和实参的关系
面试常考这三段代码,它们共同揭示一个底层事实:所有传参,都是复制一份值过去,仅此而已。
- 基本类型:int i = 10; change(i); → 方法内修改 i2 不影响外面的 i,因为传的是 10 这个数字的拷贝。
- 包装类或 String:Integer i = 10; change(i); → 表面看是对象,但 Integer 和 String 都不可变,i2 = 1 实际是新建对象并让形参指向它,原引用不变。
- 可变对象(如 StringBuilder、自定义类):StringBuilder s = new StringBuilder("a"); change(s); → 形参 s2 拿到的是 s 所存地址的副本,二者指向堆中同一个对象,所以 s2.append("b") 会改变原对象内容;但 s2 = new StringBuilder("c") 只会让 s2 指向新对象,s 仍指向原来的。
内存视角:栈里存什么,堆里放什么
理解传递机制绕不开内存模型:
- 所有局部变量(包括形参、实参)都存在栈中。
- new 出来的对象、字符串常量、静态变量等存在堆或方法区/常量池中。
- 栈中变量若为引用类型,其值就是一串内存地址(比如 0x7f8a),这个地址本身是个整数——而 Java 正是把这个整数的副本传给了形参。
换句话说,你传的从来不是对象,也不是“引用”这个抽象概念,你传的是一个地址数值的拷贝。这就彻底解释了为什么“能改内容,不能改指向”。
一句话破除所有误区
别再纠结“基本类型是值传递、对象是引用传递”这种错误划分。Java 从不区分类型来切换传递方式——它始终做同一件事:把实参当前持有的值,完整复制一份给形参。这个值,对 int 是 10,对 User 是 0x7f8a,对 null 是 0x0。复制之后,两者独立,只是在对象场景下,副本地址恰好还能找到原对象罢了。
面试应答建议
被问到时,先明确结论:“Java 只有值传递”。然后分两层说清:
- 第一层讲定义:值传递 = 传副本,引用传递 = 传本体地址(像 C++ 的 &);Java 不支持后者。
- 第二层讲现象:对象能改属性,是因为副本地址仍指向原对象;不能改引用本身,是因为形参换地址不影响实参存储的旧地址。
如果面试官追问“那为什么不叫地址传递”,可以补充:地址本身也是值,传地址的副本,仍是值传递——就像传身份证号的复印件,不是传本人。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











