Integer.valueOf() 不是简单 new Integer(),因为其内置 [-128, 127] 缓存机制,该范围内的 int 值复用同一实例;new Integer() 每次新建对象,且绕过缓存;缓存由 JVM 规范强制要求,仅对 int 参数生效,String 解析后仍依数值是否在范围内决定是否命中。

Integer.valueOf() 为什么不是简单 new Integer()?
因为 Integer.valueOf() 默认启用了 -128 到 127 范围内的对象缓存,相同值在这个区间内会复用同一个实例;而 new Integer() 每次都新建对象,必然不等。这是 JVM 规范要求的缓存行为(JLS §5.1.7),不是可选优化。
哪些输入值能命中缓存?
只有传入的 int 值在 [-128, 127] 闭区间内时,Integer.valueOf(int) 才返回缓存对象。超出该范围(比如 Integer.valueOf(1000))会走 new Integer(i) 分支,返回新对象。
常见误判场景:
- 从字符串解析再转:
Integer.valueOf("128")→ 不缓存(128 超出范围) - 计算结果:
Integer.valueOf(64 * 2)→ 缓存(128?错,64*2=128 → 不缓存) - 注意:缓存只对
int参数生效;Integer.valueOf(String)内部仍调用parseInt再调valueOf(int),所以最终是否缓存仍取决于解析后的数值
如何验证是否真的用了缓存?
用 == 比较引用即可,前提是两个对象均由 Integer.valueOf() 生成:
Integer a = Integer.valueOf(100); Integer b = Integer.valueOf(100); System.out.println(a == b); // true <p>Integer c = Integer.valueOf(200); Integer d = Integer.valueOf(200); System.out.println(c == d); // false </p>
注意:Integer c = 200; 这种自动装箱也走 valueOf(),所以同样适用;但若混用 new Integer(100),== 必为 false。
缓存范围能改吗?有啥代价?
可以,通过 JVM 启动参数 -Djava.lang.Integer.IntegerCache.high=200 扩展上限(下限固定为 -128)。但要注意:
- 该参数只在类首次初始化前生效,运行时修改无效
- 缓存对象在堆中常驻,扩大范围会增加类加载初期内存占用和 GC 压力
- 多数业务场景无需调整——-128~127 已覆盖绝大多数计数、状态码、小索引等用途
真正容易被忽略的是:缓存机制仅存在于 Integer、Byte、Short、Character 和 Boolean;Long 和 Float 的 valueOf() 方法虽存在,但不提供默认缓存(Long.valueOf() 在 JDK 9+ 对 -128~127 也加了缓存,但非规范强制)。










