integer == 比较的是引用而非值;-128~127 范围内通过 integercache 缓存复用对象,超出则每次 new 新对象,故地址不同导致 false;应统一用 equals() 或 intvalue() 比较。

因为 == 比较的是对象引用,不是数值;超出 -128~127 范围时,每次自动装箱都会创建新对象,地址不同,结果自然为 false。
缓存机制是根源
Java 在 Integer 类内部实现了静态缓存池(IntegerCache),默认预创建并复用 -128 到 127 范围内的所有 Integer 实例。这个设计是 JVM 规范强制要求的,目的是减少小整数频繁装箱带来的对象开销和 GC 压力。
- 当执行 Integer a = 127,底层调用 Integer.valueOf(127) → 返回缓存中同一个对象
- 当执行 Integer b = 128,valueOf(128) 判断超限 → 直接 new Integer(128),每次都是新对象
- 所以 a == b 实际是比较两个不同内存地址,结果必为 false
别被语法糖骗了
看似简洁的赋值写法(如 Integer x = 128)其实是编译器做的“自动装箱”,它等价于 Integer x = Integer.valueOf(128),而非 new Integer(128)。但关键区别在于:valueOf() 会查缓存,而 new 总是新建——哪怕数值相同,new 出来的对象也永远不相等。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- Integer a = new Integer(127); Integer b = new Integer(127); → false(两个 new,地址肯定不同)
- Integer a = 127; Integer b = new Integer(127); → false(一个来自缓存,一个全新对象)
- Integer a = 127; int b = 127; → true(自动拆箱后比较 int 值)
安全比较的正确姿势
只要涉及 Integer 对象之间的相等性判断,就该放弃 ==,改用更明确、更可靠的方式:
- 用 equals():它会先判 null,再比较数值,语义清晰且兼容所有范围
- 用 intValue() 强转后比基本类型:a.intValue() == b.intValue()
- 如果确定一方是基本类型 int,直接用 == 即可(JVM 自动拆箱)
缓存范围其实可以调,但没必要
系统参数 -Djava.lang.Integer.IntegerCache.high=200 可以把上限提高到 200,但下限 -128 固定不可改。不过这种调整极少有实际价值:
- 扩大缓存会增加类加载时的内存占用(哪怕只多 73 个对象,也是额外开销)
- 业务逻辑不该依赖缓存边界,否则代码脆弱且难以维护
- 真正需要高性能的场景,通常已避开包装类,直接用 int 或 LongStream 等原生结构










