对于 Java 初学者来说,“对象” 与 “引用” 的关系常常是入门路上的第一个难点 —— 为什么修改一个变量,另一个变量的值也会跟着变?为什么赋值操作后,原来的对象好像 “消失” 了?今天我们就通过Person 类演示代码,一步步拆解对象创建、引用赋值、属性修改的底层逻辑,帮你彻底理清 Java 内存中的对象交互规则。
1. 逐阶段拆解:从内存视角看代码执行
Java 中对象存储在堆内存,而对象的引用(即变量 p1、p2)存储在栈内存。我们通过 “内存图 + 执行逻辑” 的方式,逐个阶段分析代码到底在做什么。
阶段 1:创建 p1 对象并初始化
代码:
Person p1 = new Person();
p1.name = "xiaobai";
p1.age = 19;
System.out.println(p1.name); // 输出:xiaobai
System.out.println(p1.age); // 输出:19
p1.eat("fish"); // 输出:吃fish
阶段 2:创建 p2 对象,再将 p2 赋值给 p1
代码:
Person p2 = new Person();
p2.name = "xiaohei";
p2.age = 22; p1 = p2; // 这行是核心!
System.out.println(p1.name); // 输出:xiaohei
System.out.println(p2.name); // 输出:xiaohei
System.out.println(p1.age); // 输出:22
System.out.println(p2.age); // 输出:22
阶段 3:修改 p1 属性,观察 p2 变化
代码:
p1.name = "xiaohuang";
p1.age = 23;
System.out.println(p1.name); // 输出:xiaohuang
System.out.println(p2.name); // 输出:xiaohuang
System.out.println(p1.age); // 输出:23
System.out.println(p2.age); // 输出:23
2. 解析注释代码:更复杂的引用场景
代码中还有一段注释掉的代码,我们单独拿出来分析,帮你覆盖更多引用传递场景。
场景 1:直接让 p2 指向 p1 的对象(未 new 新对象)
代码:
Person p2 = p1; // 注意:没有new Person()
p2.name = "xiaoqing";
p2.age = 21; System.out.println(p1.name); // 输出:xiaoqing
System.out.println(p2.name); // 输出:xiaoqing
场景 2:方法参数传递 Person 对象
代码:
fun01(p1);
System.out.println(p1.name); // 输出:xiaohong
System.out.println(p1.age); // 输出:20
3. 总结:Java 对象引用的 3 个核心规则
通过这段代码的分析,我们可以总结出 Java 对象引用的 3 个关键规则,帮你避免踩坑:
- 引用≠对象:变量(p1、p2)是引用,存储对象的地址;对象本身存储在堆内存,引用只是 “指向” 对象的工具。
- 引用赋值会覆盖:当执行
p1 = p2时,p1 原有的引用会被覆盖,转而指向 p2 的对象;原对象若无人引用,会被 GC 回收。 - 多引用指向同一对象时,修改会同步:无论通过哪个引用修改对象属性,所有指向该对象的引用都会获取到修改后的结果。