You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中包装类与自定义对象的引用工作机制差异疑问

核心差异原因

你遇到的现象本质是两种操作逻辑的区别,叠加包装类、String的不可变特性共同导致的:

1. 自定义类案例的运行逻辑

你给出的Student类是可变类,可以任意修改对象内部的属性值:

Student s3 = s1;
s3.name = "student 3";

这两行代码的执行逻辑是:

  • 第一行:让s3和s1两个引用指向堆内存中同一个Student对象
  • 第二行:修改当前s3指向的对象内部的name属性,全程没有改变s3的指向
    因为两个引用指向同一个对象,所以通过s3修改属性后,s1读取到的自然是修改后的值。

2. 包装类/ String 案例的运行逻辑

Integer、String、Double这类都属于不可变类:类的所有成员属性都被final修饰,对象实例化后没有任何方法可以修改对象内部的数值。
你给出的代码里:

Integer c = a;
c = 30;

这两行的执行逻辑是:

  • 第一行:让c和a两个引用指向同一个值为10的Integer对象
  • 第二行:让c引用本身指向一个新的、值为30的Integer对象,完全没有修改原来的10这个对象的内容
    这里的c = 30是Java自动装箱的语法糖,等价于c = Integer.valueOf(30),这个方法只会返回新的Integer实例(小数值会复用缓存对象,但绝对不会修改已有对象的值),所以a还是指向原来的10的实例,c指向新的30的实例,输出自然不同。

验证对比

如果你把自定义的Student类也改成不可变类,就能得到和包装类完全一致的效果:

final class Student{
    final int id;
    final String name;
    // 只提供构造方法赋值,不提供setter
    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

这时候你写完Student s3 = s1;之后,根本无法修改s3指向的对象的name属性,只能写s3 = new Student(10, "student 3");让s3指向新对象,此时s1的取值完全不会变化,和包装类的表现完全一致。

内容的提问来源于stack exchange,提问作者Helsinki Red

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 07:57:02