Java包装类缓存机制本质是JVM复用常用小数值对象以减少内存分配和GC压力,核心取决于范围、创建方式与比较习惯;Integer默认缓存-128~127,Byte全范围缓存,Short/Long默认同Integer但Long不保证,Character缓存0~127,Boolean仅缓存true/false。

Java 中包装类的缓存机制,本质是 JVM 对常用小数值对象做“复用”设计,核心目的是减少堆内存分配、提升性能和降低 GC 压力。它不是所有包装类都一样,也不是所有创建方式都生效——关键在 范围、创建方式 和 比较习惯 三者协同。
Integer 缓存:-128 到 127 是默认安全区
Integer 的缓存由内部静态类 IntegerCache 实现,强制缓存区间为 -128 至 127(含端点),这是 Java 语言规范(JLS)明确要求的,所有合规 JVM 都必须支持。
- 该范围覆盖绝大多数索引、循环变量、状态码、ASCII 字符值等高频整数
- 超出此范围(如 128、-129),每次调用
Integer.valueOf()或自动装箱都会新建对象 - 可通过 JVM 参数
-XX:AutoBoxCacheMax=200扩大上限(仅影响上限,下限 -128 固定不可调)
哪些操作能命中缓存?哪些绕过?
缓存只对两种创建路径有效:
-
自动装箱:如
Integer a = 100;—— 编译器自动转为Integer.valueOf(100) -
显式调用 valueOf():如
Integer b = Integer.valueOf(100); -
new 构造器完全绕过缓存:如
new Integer(100)每次都生成新对象,即使值在 -128~127 内
这意味着:Integer x = 100; Integer y = new Integer(100); 中,x == y 一定是 false。
其他包装类的缓存策略差异
并非所有数字包装类缓存逻辑一致:
- Byte:缓存全部可能值(-128 ~ 127),无例外
-
Short 和 Long:默认也缓存 -128 ~ 127,但
Long的缓存行为在部分 JDK 版本中可能不启用(依赖实现,不保证) - Character:仅缓存 Unicode 值 0 ~ 127(即 ASCII 可见字符和控制字符)
-
Boolean:只缓存
true和false两个实例,任何布尔装箱都复用它们
== 和 equals() 的坑,必须警惕
缓存机制让 == 在某些情况下“碰巧”返回 true,但这只是引用相等的副产品,不是设计目的:
-
Integer a = 127; Integer b = 127; a == b → true(同缓存对象) -
Integer c = 128; Integer d = 128; c == d → false(不同对象) -
Integer e = 127; Integer f = new Integer(127); e == f → false(一个缓存,一个新堆对象)
所以:只要涉及包装类对象比较,一律用 .equals();集合(如 Map<character integer></character>)中做值判断时,尤其不能用 ==。

















