题目
Java中方法参数传递是值传递还是引用传递?请通过代码示例说明
信息
- 类型:问答
- 难度:⭐⭐
考点
参数传递机制,基本数据类型与引用类型的区别,内存模型
快速回答
Java中所有参数传递都是值传递:
- 基本数据类型传递的是值的副本
- 引用类型传递的是引用的副本(即对象地址的拷贝)
- 方法内修改引用指向的对象会影响原对象,但重新赋值引用不会影响原引用
1. 核心原理说明
Java中方法参数传递本质是值传递(Pass by Value):
- 对于基本数据类型(int, double等),传递的是实际值的副本
- 对于引用类型(对象、数组),传递的是引用的副本(即对象内存地址的拷贝)
- 方法内对引用副本的操作:
- 修改引用指向的对象内容 → 影响原对象
- 修改引用本身(指向新对象)→ 不影响原引用
2. 代码示例
public class ParameterPassingDemo {
public static void main(String[] args) {
// 基本数据类型示例
int num = 10;
System.out.println("基本类型修改前: " + num); // 输出 10
modifyPrimitive(num);
System.out.println("基本类型修改后: " + num); // 输出 10(未改变)
// 引用类型示例
StringBuilder sb = new StringBuilder("Hello");
System.out.println("引用类型修改前: " + sb); // 输出 Hello
modifyReference(sb);
System.out.println("引用类型修改后: " + sb); // 输出 Hello World
// 引用重新赋值示例
StringBuilder sb2 = new StringBuilder("Original");
System.out.println("重新赋值前: " + sb2); // 输出 Original
reassignReference(sb2);
System.out.println("重新赋值后: " + sb2); // 输出 Original(未改变)
}
static void modifyPrimitive(int a) {
a = 20; // 修改副本,不影响原始值
}
static void modifyReference(StringBuilder builder) {
builder.append(" World"); // 通过副本修改对象内容
}
static void reassignReference(StringBuilder builder) {
builder = new StringBuilder("New Value"); // 引用副本指向新对象
}
}3. 内存模型图解

- 基本类型:main栈帧中的num=10,方法栈帧中的a是独立副本
- 引用类型:main栈帧的sb和modifyReference栈帧的builder指向同一堆内存对象
- 重新赋值:reassignReference栈帧中的builder指向新对象,main栈帧的sb2不变
4. 常见错误
- 误认为传递引用类型时是引用传递(实际是传递引用的值)
- 期望在方法内重新赋值引用能改变原始引用(如示例中的sb2)
- 混淆“修改引用”和“修改引用指向的对象”:
- builder.append() → 修改对象内容(影响原对象)
- builder = new StringBuilder() → 修改引用副本(不影响原引用)
5. 最佳实践
- 避免在方法中修改传入的参数对象(除非明确需要副作用)
- 需要修改引用指向时,返回新对象而不是尝试修改参数
- 对不可变对象(如String)的操作要特别注意:
String str = "abc"; modifyString(str); // 方法内任何修改都会创建新对象 System.out.println(str); // 仍输出"abc"
6. 扩展知识
- Java与C++区别:C++支持真正的引用传递(使用&符号)
- 特殊类型处理:数组作为参数时行为与对象一致
- JVM实现:局部变量表(Local Variable Table)存储基本类型值和对象引用
- 防御性编程:当方法接收可变对象时,考虑使用clone()创建副本避免意外修改