Java包装类缓存机制以Integer最典型,-128至127范围内的值通过valueOf()或自动装箱复用缓存对象,使==比较为true;超出该范围则新建对象,==为false;推荐用equals()比较值相等,且仅Integer支持通过JVM参数调整缓存上限。

Java 中包装类的缓存机制,最典型体现在 Integer 类上,它让一定范围内的整数对象可以复用,避免重复创建,从而节省内存并提升性能。理解这个机制的关键,在于知道它“什么时候生效”、“为什么只对部分值有效”,以及“如何影响 == 和 equals 的行为”。
缓存范围:-128 到 127 是默认安全区
Integer 类内部维护了一个静态缓存数组,预创建了从 -128 到 127(含)共 256 个 Integer 对象。当你用 Integer.valueOf(int) 或自动装箱(如 Integer i = 100;)创建这个范围内的整数时,JVM 直接返回缓存中的对象,而不是新建实例。
- ✅
Integer a = 100; Integer b = 100;→a == b为 true(指向同一缓存对象) - ❌
Integer c = 200; Integer d = 200;→c == d为 false(各自 new 出来的新对象) - ⚠️ 注意:
new Integer(100)总是新建对象,绕过缓存,所以new Integer(100) == Integer.valueOf(100)为 false
valueOf() 是触发缓存的正确方式
直接使用构造器(new Integer(x))已被弃用,且不走缓存;而 Integer.valueOf(x) 是推荐的、可利用缓存的工厂方法。其他基本类型包装类也有类似设计:
-
Byte.valueOf(byte):全部 256 个值都缓存(-128 ~ 127) -
Short.valueOf(short)和Long.valueOf(long):也缓存 -128 ~ 127,但规范未强制要求超出该范围的行为 -
Character.valueOf(char):缓存 \u0000 ~ \u007F(0~127) -
Boolean.valueOf(boolean):只返回两个静态常量TRUE/FALSE,本质也是缓存
== 比较失效的常见陷阱
因为缓存的存在,用 == 比较两个 Integer 对象时,结果取决于数值是否落在缓存范围内,这容易引发隐蔽 bug:
立即学习“Java免费学习笔记(深入)”;
- 看似相等的代码:
Integer x = 127; Integer y = 127; System.out.println(x == y);→ 输出 true - 仅改一个数:
Integer x = 128; Integer y = 128;→x == y变成 false - ✅ 正确做法:统一用
equals()判断逻辑相等(它先判 null,再比 int 值),不受缓存影响
可配置的缓存上限(仅限 Integer)
JVM 启动参数 -Djava.lang.Integer.IntegerCache.high=200 可扩大 Integer 缓存的上限(最小仍为 -128)。但注意:
- 该参数只对
Integer有效,其他包装类不可调 - 必须在 JVM 启动时设置,运行时无法修改
- 扩大缓存会增加类加载时的内存开销,需权衡利弊


















