new Integer(127) == new Integer(127) 为 false,因为 new 总是创建堆中独立对象,== 比较的是内存地址而非值,即使数值相同、在缓存范围内,也绝不复用对象。

用 == 比较 new Integer(127) 和 new Integer(127) 为什么是 false
因为 == 比较的是对象引用,不是值。即使两个 new Integer(127) 的值相同,它们也是堆上两个独立的对象,内存地址不同。
常见错误现象:new Integer(127) == new Integer(127) 返回 false,但 new Integer(100) == new Integer(100) 同样是 false——别被“-128~127 缓存”误导,new 总是绕过缓存,永远新建对象。
-
new强制在堆上分配新实例,和常量池/缓存无关 - 包装类的
==行为和Object一致:只看是否同一块内存 - 想比值,必须用
.equals()或先拆箱(如int a = i1.intValue();)
为什么 Integer.valueOf(127) == Integer.valueOf(127) 有时是 true
因为 valueOf() 在 -128 到 127 范围内会复用缓存对象,所以返回的是同一个实例。但这只是优化,不是语义保证;超出范围就又变成两个不同对象。
关键区别在于构造方式:new 是“我要一个新对象”,valueOf() 是“给我一个值匹配的对象(能复用就复用)”。所以:
-
Integer.valueOf(127) == Integer.valueOf(127)→true(缓存命中) -
Integer.valueOf(128) == Integer.valueOf(128)→false(缓存未命中,各自新建) -
new Integer(127) == Integer.valueOf(127)→false(一个是堆新对象,一个是缓存对象)
比较包装类值的正确姿势
不要依赖 == 做值比较,尤其当对象来源不确定(比如来自 JSON 解析、反射、泛型容器)时,== 极易出错。
- 统一用
.equals():它已重写,会先判空再比值,安全可靠 - 若确定非 null 且需避免装箱开销,可显式拆箱:
i1.intValue() == i2.intValue() - 注意
null风险:直接调.equals()没问题;但i1.intValue() == i2.intValue()遇到null会抛NullPointerException - Java 7+ 可用
Objects.equals(i1, i2),内部做了 null 安全处理
String、Boolean 等其他包装类也适用同样规则吗
适用,但细节不同:Boolean 的 valueOf() 总是返回缓存对象(只有 TRUE/FALSE 两个),所以 Boolean.valueOf(true) == Boolean.valueOf(true) 永远是 true;而 new Boolean(true) == new Boolean(true) 仍是 false。
String 不是包装类,但常被拿来类比:字面量 "abc" == "abc" 是 true(字符串常量池),但 new String("abc") == new String("abc") 是 false——原理一样,都是 == 看引用。
核心没变:只要用了 new,你就放弃了所有缓存和复用,得到的是全新对象。

















