Java中所有方法参数都是值传递,基本类型传值副本,对象类型传引用副本;修改对象属性会影响原对象,但重新赋值形参引用则不会;String等不可变类因创建新对象而看似被修改。

Java中所有方法参数都是值传递,没有引用传递。所谓“值传递”,是指方法接收的是实参的副本,而不是实参本身;即使传入的是对象,传递的也只是对象引用的副本,而非引用本身。
基本类型参数:传递真实值的拷贝
对于 int、double、boolean 等基本类型,方法接收到的是该变量值的一个完全独立副本。修改形参不会影响原始变量。
例如:
int a = 10;
change(a);
System.out.println(a); // 输出仍是 10
立即学习“Java免费学习笔记(深入)”;
void change(int x) { x = 20; }
这里 x 是 a 的副本,x 的修改与 a 无关。
对象类型参数:传递引用的副本
当传入一个对象(如 String、ArrayList、自定义类实例)时,实际上传递的是该对象引用(即内存地址)的一个副本。这个副本和原引用指向同一个堆内存中的对象。
因此,在方法内通过该引用修改对象的属性(比如 list.add()、obj.name = "new"),会影响原对象;但若在方法内让形参引用指向新对象(如 obj = new Person()),则不会改变原始引用所指的对象。
例如:
Person p = new Person("Alice");
modify(p);
System.out.println(p.name); // 输出 "Bob"
void modify(Person person) {
person.name = "Bob"; // ✅ 修改对象内容,生效
person = new Person("Charlie"); // ❌ 只改变副本引用,不影响 p
}
String 和包装类是特例:不可变性掩盖了值传递本质
String、Integer、Double 等是不可变类(immutable)。它们看似“被修改”,其实是创建了新对象并让引用指向它。由于传入的是引用副本,方法内重新赋值对原引用无影响。
例如:
String s = "hello";
changeStr(s);
System.out.println(s); // 输出 "hello",不是 "world"
void changeStr(String str) {
str = "world"; // 创建新字符串,str 指向新对象,原 s 不变
}
想真正实现“引用传递效果”?靠返回值或包装容器
Java 无法直接修改传入的引用本身,但可通过以下方式间接达成目的:
- 方法返回新对象,由调用方重新赋值: s = changeStr(s);
- 传入可变容器(如 AtomicInteger、StringBuilder、List、自定义包装类)来承载数据
- 将多个相关值封装进一个对象,传对象引用并在内部修改其字段
这些做法不改变 Java 的值传递本质,而是利用对象可变性或显式赋值来达到预期效果。










