Java中包装类用==比较实际比的是对象地址而非值,仅-128~127范围因缓存可能为true;应使用equals()或Objects.equals()比较数值,避免null异常和自动拆箱风险。

Java 中包装类(如 Integer、Long、Boolean)用 == 比较数值,表面看是“相等判断”,实际比的是对象地址,不是值——这是最常被忽略却后果严重的底层陷阱。
== 比的不是数,是对象在堆里的“门牌号”
Integer 是类,本质是对象。== 对引用类型来说,只判断两个变量是否指向**同一个内存地址**。哪怕数值完全一样,只要不是同一个对象,== 就返回 false。
- Integer a = 127; Integer b = 127; → a == b 为 true(因为 -128 ~ 127 被缓存,复用同一对象)
- Integer c = 128; Integer d = 128; → c == d 为 false(超出缓存范围,各自 new 出不同对象)
- 这种“有时对、有时错”的行为,根本不可靠,也不是 bug,而是设计使然
equals() 才真正比较“数值内容”
Integer 重写了 equals() 方法,内部逻辑是:先校验类型,再取出 int 值做基本类型比较。所以它不关心对象在哪,只关心“装的数是不是一样”。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- a.equals(b)、c.equals(d) 都返回 true(只要数值相同)
- 但直接调用 a.equals(b) 有风险:若 a 为 null,会抛 NullPointerException
- 更稳妥写法是 Objects.equals(a, b),它自动处理 null,两个都 null 返回 true,一个 null 返回 false
别让自动拆箱偷偷把你拖进空指针坑
当你写 if (integer == 5),编译器会自动转成 if (integer.intValue() == 5) —— 这就是自动拆箱。一旦 integer 是 null,intValue() 立刻抛 NPE。
立即学习“Java免费学习笔记(深入)”;
- 所有涉及 ==、>、<、compareTo() 的操作,只要包装类变量可能为 null,就隐含拆箱风险
- Objects.equals() 安全,因为它不拆箱;而 compareTo() 和 intValue() 都要求非 null
- 如果真要比较大小,先用 Objects.nonNull(a) && Objects.nonNull(b),再调用 a.compareTo(b) 或解包比较
记住这个分工:== 留给基本类型,equals 留给包装类
int x = 5; int y = 5; → x == y 安全又高效,因为它是纯数值比较。
- Integer i = 5; Integer j = 5; → i == j 不可靠,i.equals(j) 或 Objects.equals(i, j) 才是正确姿势
- Boolean、Character 等其他包装类同理:== 可能因缓存“碰巧”成功,但绝不该依赖
- 尤其在数据库查询、RPC 返回、Optional.orElse(null) 等场景中,包装类为 null 极其常见,必须默认按 null 安全方式处理

















