前言
JAVA对于对象类型的参数传递,主流解释是:“JAVA传递对象类型的时候,传递的不是对象本身,而是对象的地址”。这句话容易让人误解为这是引用传递,确实这种传递方式表现得类似于引用传递,但实际上JAVA仍然是值传递。
0.太长不看
核心区别:
值传递:传递引用的副本(将对象的地址复制到新的一块内存中传递)
引用传递:传递引用本身(直接传递对象的地址)
1.图片解释
看下面的例子:
我有一个类Food,三个对象Food 鸡蛋、Food 苹果、Food 西瓜,一个引用Food 引用,一个方法 void eat(Food food)
对于对象的“引用传递”

对于对象的“值传递”

接下来,我想在eat中修改原来的“Food 引用”,让其引用苹果,那么就发生区别了。比如要将“Food 引用”改成引用“Food 苹果”,那么就回出现下面的区别:
对于对象的“引用传递”

对于对象的“值传递”

看到区别了吗,引用传递可以在eat()内部修改“Food 引用”本身,让其转而引用“Food 苹果”;值传递,在eat()内部只能修改“Food 引用的副本”,不能修改“Food 引用”本身。
2.代码示例:
class Food {
String name;
Food(String name) {
this.name = name;
}
void eat() {
System.out.println("Eating " + name);
}
}
public class FoodExample {
public static void main(String[] args) {
Food egg = new Food("Egg");
Food apple = new Food("Apple");
System.out.println("=== 初始状态 ===");
System.out.println("main方法中: egg指向=" + egg.name);
System.out.println("main方法中: apple指向=" + apple.name);
System.out.println("\n=== 调用eat方法,传入egg ===");
eat(egg, apple);
System.out.println("\n=== eat方法调用后 ===");
System.out.println("main方法中: egg指向=" + egg.name); // 仍然是Egg!
System.out.println("main方法中: apple指向=" + apple.name);
}
// 尝试在方法中修改引用指向
static void eat(Food food, Food newFood) {
System.out.println("eat方法开始时: food指向=" + food.name);
// 尝试修改引用指向apple
food = newFood; // 这里只修改了副本引用!
System.out.println("eat方法修改后: food指向=" + food.name);
food.eat(); // 这里吃的是Apple,但只在方法内有效
}
}
输出结果:
=== 初始状态 ===
main方法中: egg指向=Egg
main方法中: apple指向=Apple
=== 调用eat方法,传入egg ===
eat方法开始时: food指向=Egg
eat方法修改后: food指向=Apple Eating Apple
=== eat方法调用后 ===
main方法中: egg指向=Egg
main方法中: apple指向=Apple
3. 内存模型图解
调用 eat(egg, apple) 时的内存状态:
text
栈内存: main方法栈帧: egg ─────→ [Food对象] name="Egg" apple ─────→ [Food对象] name="Apple" eat方法栈帧: food (egg的副本) ───→ [Food对象] name="Egg" newFood (apple的副本) → [Food对象] name="Apple"
执行 food = newFood 后:
text
main方法栈帧: (未变化) egg ─────→ [Food对象] name="Egg" apple ─────→ [Food对象] name="Apple" eat方法栈帧: food (现在指向apple) ──────────→ [Food对象] name="Apple" newFood ──────────────────────┘
4. 关键区别总结
| 特征 | Java实际(值传递引用) | 真正的引用传递 |
|---|---|---|
| 传递内容 | 引用的副本 | 引用本身 |
| 修改引用指向 | 只影响方法内的副本 | 影响原始引用 |
| 修改对象内容 | 会影响原始对象 | 会影响原始对象 |
| 比喻 | 给钥匙复印件 | 给钥匙原件 |
10万+

被折叠的 条评论
为什么被折叠?



