Java中所有方法参数传递都是值传递,基本类型传数值副本,引用类型传地址副本;形参修改基本类型不影响实参,修改引用类型对象属性会影响实参,但重新赋值引用不会影响实参。

Java 中所有方法参数传递都是值传递,没有例外。关键不是“传什么类型”,而是“传什么内容”——基本类型传数值副本,引用类型传地址副本。理解这点,就能预判方法内修改是否影响外部变量。
基本类型:传的是数值本身的一份拷贝
int、double、boolean 等变量的值直接存在栈中。调用方法时,JVM 把这个值复制一份给形参,两者完全独立。
- 形参在自己栈帧里操作,比如把 int 形参从 5 改成 100,外部原始变量仍是 5
- 方法执行完,形参副本随栈帧一起销毁,原始变量不受任何干扰
- 典型例子:
void modify(int x) { x = 42; }调用后实参值不变
引用类型:传的是堆中地址的一份拷贝
Person、ArrayList、String 等变量本身存的是对象在堆中的地址(比如 0x7a8b),这个地址值被复制给了形参。
- 实参和形参初始指向同一块堆内存,所以通过形参改对象属性(如
p.name = "Tom"),外部能立刻看到变化 - 但若在方法内让形参指向新对象(如
p = new Person()),只是改了副本的地址,实参仍指着原来的对象 - 这就像你和同事各拿一张同一仓库的门牌号纸条;你按纸条进去贴标签,仓库变了;你涂改自己那张纸条,对方照旧能找到原仓库
不可变类型(String、Integer):地址副本 + 内容不可改 = 表面“改不动”
它们也是引用类型,同样传地址副本。但每次看似“修改”,实际都新建对象并返回新地址。
立即学习“Java免费学习笔记(深入)”;
-
s += "world"不是改原字符串,而是让形参指向新字符串对象 - 外部实参仍持有旧字符串的地址,自然看不到变化
- 这不是“传引用失效”,而是不可变性叠加值传递的自然结果
- 真要可变操作,换用
StringBuilder或StringBuffer
验证方式:看 identityHashCode 和调试栈帧
最直观的办法是运行时观察内存行为:
- 用
System.identityHashCode(obj)打印实参与形参的对象哈希码:相同说明指向同一堆对象 - 在 IDE(如 IDEA)中打断点,进入方法后查看两个变量的内存地址:栈中地址不同,证明是两个独立变量
- 执行
p = new Person()后再查哈希码,形参的变了,实参的保持不变


















