integer缓存机制的核心在于valueof()方法的缓存逻辑和==比较地址的本质:-128~127是jdk默认缓存区间,范围内复用对象,范围外新建对象;==比较地址,故需用equals()或拆箱确保数值比较安全。

理解Integer缓存机制的关键,不是背数字范围,而是看清“自动装箱如何调用valueOf”和“==比较的是地址还是值”这两层逻辑。-128到127不是魔法数字,而是JDK默认设定的缓存区间;所谓“陷阱”,本质是开发者误把引用比较(==)当成了数值比较。
自动装箱背后其实是valueOf()在干活
写 Integer a = 127; 看似简单,编译器实际把它转成:Integer a = Integer.valueOf(127);。同理,Integer b = 128; 对应的是 Integer.valueOf(128)。真正决定对象是否复用的,是valueOf方法内部的判断逻辑:
- 若参数在 IntegerCache.low(-128) 和 IntegerCache.high(默认127) 之间,直接返回缓存数组里的已有对象
- 否则,执行 new Integer(i),创建全新对象
== 比较的是对象地址,不是数值大小
这是绝大多数困惑的根源。当两个Integer变量指向同一个缓存对象时,== 返回 true;指向两个独立new出来的对象时,即使数值完全一样,== 也返回 false:
- Integer a = 127, b = 127; → 共享缓存对象 → a == b 是 true
- Integer c = 128, d = 128; → 各自 new 出不同对象 → c == d 是 false
- Integer e = new Integer(127), f = new Integer(127); → 两个显式 new 的对象 → e == f 也是 false
安全比较的三种可靠方式
绕开陷阱不靠记忆范围,而靠明确意图:
- 比数值:统一用 .equals() —— Integer重写了该方法,会先判null再比int值
- 比基本类型:用 intValue() 拆箱后比较,如 a.intValue() == b.intValue()
- 混合类型比较(Integer vs int):Java会自动拆箱,Integer a = 127; int b = 127; a == b 总是安全的(此时==实际比较的是两个int)
缓存范围其实可以调大,但不建议
通过JVM参数 -Djava.lang.Integer.IntegerCache.high=200 可以把上限提到200,但这只影响当前应用,且无法解决跨服务、跨版本兼容性问题。更严重的是:依赖这个配置会让代码行为变得隐式且脆弱。真实项目中,应视为“-128~127是唯一可预期的缓存区间”,超出范围一律按新对象处理。










