Java中所有参数传递都是值传递:基本类型传数值副本,修改不影响实参;引用类型传地址副本,修改对象内容影响实参,但重赋值指向新对象则不影响。

Java 中所有参数传递都是值传递,没有例外。关键在于理解“值”对不同数据类型意味着什么:基本类型传的是数值本身,引用类型传的是对象地址的副本。
基本数据类型:传值即传数
int、double、char、boolean 等类型作为参数时,方法收到的是实参值的一份独立拷贝,存在栈中,与原变量完全隔离。
- 形参在方法内被修改,不影响外部原始变量
- 哪怕在方法里把 int 参数改成 100,main 里的原始 int 还是原来的值
- 本质是栈内存复制——两个变量各自占位,互不干扰
引用数据类型:传值即传地址副本
数组、自定义类对象、List 等作为参数时,传递的是堆中对象地址的副本(不是对象本身,也不是引用本身,而是那个地址的拷贝)。
- 通过该地址修改对象内部状态(如 arr[0] = 999 或 person.name = "李四"),外部对象会同步变化
- 但如果给形参重新赋值(如 arr = new int[]{1,2} 或 p = new Person()),只是让形参指向新地址,原变量仍指向旧对象,不受影响
- String 是特例:虽属引用类型,但不可变;方法内 p = "hello" 实质是新建字符串并让形参指向它,原 String 变量不变
常见误区与验证方式
很多人误以为“对象传进去就能改外面”,其实只在操作对象内容时成立;一旦重赋引用,就断开了联系。
立即学习“Java免费学习笔记(深入)”;
- 判断是否影响外部:看操作的是“对象里的字段”还是“形参这个变量本身”
- 调试时可打印对象的哈希码(如 obj.hashCode()),若前后一致,说明仍是同一对象;若变了,说明形参已指向新实例
- 交换两个变量值无法靠简单 swap 方法实现——因为基本类型传值、对象传地址副本,都做不到真正交换引用本身
如何安全地修改外部状态
如果确实需要让方法影响外部数据,有几种可靠做法:
- 用包装类或可变容器(如 AtomicInteger、StringBuilder、自定义 Holder 类)封装基本值
- 传入数组(哪怕单元素 int[]),通过索引修改内容
- 返回新对象或新值,在调用处主动赋值(推荐,符合函数式思想)
- 避免在方法内对形参重新 new 对象,除非明确不需要影响原始引用


















