面试官:Integer 缓存池到底管啥用?(附图解)
理解装箱缓存,写出高性能、低 Bug 的 Java 代码
形式:对话 + 图解 + 代码实验
场景:面试 & 源码解析
引言
面试官老王:小陈,Integer x = 127; Integer y = 127;
为什么 x == y
为真,而 128
就不行?
候选人小陈:这背后是 Integer 缓存池 在搞事情!
1. 什么是 Integer 缓存池?
graph TD
A[JVM 启动] --> B[初始化 IntegerCache]
B --> C[缓存 -128~127 的 Integer 对象]
应用代码 -->|自动装箱| D[先查缓存 -> 命中返回同对象]
- JDK 5 引入,类
java.lang.Integer.IntegerCache
在 类加载阶段 一次性创建 -128~127 的Integer
实例并放数组。 - 自动装箱或
valueOf(int)
时,若数值落在范围内,直接返回缓存对象;否则新建Integer
。
2. 第一次对话:比较操作踩坑
面试官:那我以后都用 ==
比较 Integer
就行?
小陈:可千万别!==
比较的是 引用地址。只有缓存命中时才相同,超出范围就翻车。
Integer a = 127, b = 127;
System.out.println(a == b); // true
Integer c = 128, d = 128;
System.out.println(c == d); // false
✔️ 对话 1
3. 源码探秘
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
默认 low=-128
, high=127
。high
可通过 JVM 参数 -XX:AutoBoxCacheMax=<N>
调大。
4. 第二次对话:为什么是 -128~127?
面试官:范围怎么定的?凭啥不是 0~255?
小陈:这是 byte 的取值范围(-128~127)。
- 早年 Java 频繁使用
byte
当数组索引/IO 缓冲,命中率高。 - 兼顾内存占用与命中效果。
✔️ 对话 2
5. 性能收益与注意事项
维度 | 说明 |
---|---|
内存 | 缩减频繁装箱时的堆对象数量 |
GC | 减少小整数垃圾,降低 Young GC 触发 |
线程安全 | 缓存对象是 不可变,多线程共享无忧 |
陷阱 | 误用 == 、缓存范围外的数字造成隐患 |
6. 扩大缓存的实践
java -XX:AutoBoxCacheMax=1024 MyApp
启动后
high
变为 1024,自动装箱 0~1024 都复用缓存。适合 大量小整数 的业务,如电商库存扣减。
7. 其他包装类也有缓存吗?
Long
:同样 -128~127Short
、Byte
、Character
:各自全范围缓存Boolean
:只缓存true/false
两个实例
8. 总结口诀
装箱先查池,-128~127 默认齐;比较用 equals,== 需看值。
掌握 Integer 缓存池原理,写出更健壮、更高效的代码!