Java包装类缓存机制是JVM对常用小数值对象预创建复用,以减少内存分配、降低GC压力、提升性能;Integer缓存-128~127(规范强制),Byte全范围缓存,Short/Long默认-128~127,Character缓存0~127,Boolean仅缓存TRUE/FALSE,Float/Double无缓存;仅valueOf()和自动装箱触发缓存,new构造器不触发;比较应使用equals()而非==。

Java包装类的缓存机制,本质是JVM对常用小数值对象做预创建和复用,目的是减少内存分配、降低GC压力、提升性能。它不是“所有值都缓存”,而是有明确范围、特定触发方式、且因类而异。
缓存只在特定范围生效
不同包装类的缓存区间不同,且不可一概而论:
- Integer:固定缓存 -128 到 127(含两端),这是Java语言规范强制要求,所有合规JVM都必须支持
- Byte:全范围缓存(-128 ~ 127),因为其取值范围本身就被限制在此
- Short / Long:默认也缓存 -128 ~ 127,但Long的缓存行为不保证跨JDK版本一致
- Character:缓存 Unicode 值 0 ~ 127(即ASCII字符集)
-
Boolean:仅缓存两个实例——
Boolean.TRUE和Boolean.FALSE - Float / Double:无缓存,浮点数精度和范围导致缓存无实际意义
缓存只对特定创建方式有效
不是所有生成包装类对象的方式都能命中缓存:
- ✅ 自动装箱(如
Integer a = 100;)→ 编译器转为Integer.valueOf(100)→ 触发缓存 - ✅ 显式调用 valueOf()(如
Integer b = Integer.valueOf(100);)→ 直接走缓存逻辑 - ❌ new 构造器(如
new Integer(100))→ 总是新建堆对象,完全绕过缓存
这意味着:Integer x = 100; 和 Integer y = new Integer(100); 虽然值相同,但 x == y 一定为 false。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
缓存比较必须用 equals(),不能依赖 ==
== 比较的是引用是否指向同一对象,而缓存只是让某些值“碰巧”复用对象——这不是语义保证,而是实现优化:
-
Integer a = 127, b = 127;→a == b为 true(同缓存对象) -
Integer c = 128, d = 128;→c == d为 false(各自新建) -
Integer e = 127, f = Integer.valueOf(127);→e == f为 true -
Integer g = 127; Boolean h = true;→g == h编译不通过(类型不同)
只要涉及包装类对象的内容相等判断,一律应使用 .equals(),尤其在集合键值操作、条件判断中。
缓存可微调但不推荐
仅 Integer 支持通过JVM参数扩展上限:
-
-Djava.lang.Integer.IntegerCache.high=200或-XX:AutoBoxCacheMax=200 - 下限 -128 固定不可改,上限调整仅影响 >127 的部分
- 实际项目中极少需要修改,反而可能破坏可移植性和团队认知一致性

















