Java只有值传递,没有引用传递;本质是传递实参的副本:基本类型传数值副本,引用类型传地址副本,故修改对象属性会影响外部,但重新赋值不会。

Java 只有值传递,没有引用传递——这句话不是结论,而是理解的起点。大厂面试官问这个问题,根本不在意你能不能背出标准答案,而在看你能不能用代码讲清“为什么形参改了对象内容,外部却感知到了;而重新赋值后,外部又完全没影响”。
值传递的本质:传的是“地址的副本”,不是“对象本身”
很多人卡在“既然传的是地址,那不就是引用传递吗?”这个误区。关键要明白:地址本身是值,就像 int 类型的 100 是一个值,对象的内存地址(比如 366712642)也是一个整数值。Java 把这个地址值拷贝一份给形参,所以形参和实参持有相同的地址值,指向堆中同一块对象。
- 修改对象内部属性(如 user.setName("李四")),是通过地址找到真实对象并操作它——外部当然看到变化
- 让形参指向新对象(如 u = new User("王五")),只是把形参变量里存的那个地址值换掉了,实参变量里的地址值毫发无损
- 基本类型更直观:传的是 5 的副本,你在方法里把它改成 10,不影响外面那个原始的 5
用 hashCode 和 identityHashCode 看清真相
面试时如果被追问“怎么证明传的是地址值?”,别只说理论,直接亮代码证据:
- 对普通对象,用 obj.hashCode()(前提是没重写,否则用 System.identityHashCode(obj))打印实参和形参的地址值,结果一致 → 说明它们指向同一块堆内存
- 对集合类(如 ArrayList),必须用 System.identityHashCode(),因为它的 hashCode() 是按元素内容算的,不能反映内存地址
- 运行后输出两行相同数字,比任何解释都有力
避开高频陷阱表述
面试中千万别说“Java 是值传递,但引用类型传的是引用”,这等于自相矛盾。也别模糊地说“传的是对象的引用”,而要说“传的是对象引用的值”或“传的是内存地址的副本”。后者才是精准表达。
- “引用传递”在 Java 中根本不存在——语言规范里没有这个概念
- “对象是传引用”是常见误传,混淆了“变量持有引用”和“参数传递方式”两个层面
- 真正决定传递方式的,是调用时 JVM 怎么把实参的值塞进栈帧——永远是复制一份
结合业务场景讲出深度
如果面试官接着问“那你在项目里怎么利用这个机制避免副作用?”,就到了体现工程意识的时候:
- 对外提供 API 时,若入参是 List 或 Map,不直接修改它,而是先 new ArrayList(input) 做防御性拷贝
- DTO 对象作为方法参数,习惯性用 final 修饰形参,既提醒自己不重新赋值,也向协作方传递语义
- 排查线上 bug 时,发现某个 service 方法里 user.setXXX() 导致上游数据异常,第一反应就是检查是否误用了共享对象,而不是怀疑传参逻辑有问题
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











