Java包装类的equals()比较值,==比较引用;因缓存机制,Integer等在-128~127范围内==可能为true,但本质仍是引用比较,跨类型equals返回false,建议值比较统一用equals()或Objects.equals()。

Java 中基本类型包装类(如 Integer、Boolean、Character 等)的 equals() 和 == 行为差异,核心在于:前者比较的是**值是否相等**,后者比较的是**引用是否指向同一个对象**(即内存地址是否相同)。但要注意,由于自动装箱和缓存机制的存在,== 在某些情况下“看似”也成立,容易造成误解。
包装类的 == 比较本质是引用比较
== 对于包装类变量,判断的是两个变量是否引用同一个对象。即使它们封装的值相同,只要不是同一个对象实例,结果就是 false。
- 例如:
Integer a = new Integer(100); Integer b = new Integer(100);→a == b为false(两个独立对象) - 再如:
Integer c = 100; Integer d = 100;→c == d可能为true,但这不是因为值相等,而是因为Integer对 -128 到 127 范围内的值做了缓存,两次赋值复用了同一个缓存对象
包装类的 equals() 比较的是解包后的值
equals() 方法在包装类中被重写,逻辑是先检查是否为 null,再确认类型一致,最后比较内部基本类型的值(即调用 intValue()、booleanValue() 等)。
- 例如:
Integer x = new Integer(100); Integer y = new Integer(100);→x.equals(y)为true - 跨类型比较会返回
false:new Integer(100).equals(new Long(100))是false(类型不同,直接返回) - 与
null比较安全:Integer z = null; z.equals(100)抛出NullPointerException;但Objects.equals(z, 100)更稳妥
缓存范围导致 == 行为不一致(尤其注意 Integer)
Java 规范要求 Boolean、Byte、Character(\u0000–\u007f)、Short、Integer(-128 至 127)必须缓存,其他范围或实现可选。这意味着:
立即学习“Java免费学习笔记(深入)”;
-
Integer i1 = 127; Integer i2 = 127;→i1 == i2为true -
Integer i3 = 128; Integer i4 = 128;→i3 == i4很可能为false(取决于 JVM 实现,但 OpenJDK 默认不缓存) -
Long l1 = 127L; Long l2 = 127L;→l1 == l2不保证为true(Long缓存未强制要求)
实际开发建议
为避免隐晦 bug,应遵循以下原则:
- 比较包装类的“值”时,**一律使用
equals()**(或Objects.equals(a, b)防空) - 避免用
==比较包装类,除非你明确知道在缓存范围内且有意依赖对象同一性(极少见) - 基本类型之间或基本类型与包装类比较时,优先用
==(会自动拆箱),但需确保包装类非null,否则抛NullPointerException - 需要判空时,用
Objects.nonNull()或显式!= null,不要依赖==的副作用










