java包装类缓存机制本质是jvm复用常用小数值对象以减少内存分配、降低gc压力、提升性能,关键取决于数值范围、创建方式(仅自动装箱和valueof生效)与比较习惯(须用equals而非==),integer默认缓存-128~127,byte全范围缓存,short/long同integer但long不保证,character缓存0~127,boolean仅缓存true/false,float/double无缓存。

哪些操作能命中缓存?
只有两种方式会复用缓存对象:
-
自动装箱:如
Integer a = 100;—— 编译器自动转为Integer.valueOf(100) -
显式调用 valueOf():如
Integer b = Integer.valueOf(100);
哪些操作完全绕过缓存?
以下写法每次都会新建对象,哪怕值在 -128~127 内:
-
new Integer(100):构造器已从 Java 9 起被标记为@Deprecated,且不走缓存 - 反射创建、序列化反序列化、JSON 解析(如 Jackson 默认用 new)等非标准路径
其他包装类的缓存情况
并非所有包装类策略一致:
- Byte:缓存全部取值范围(-128 ~ 127),因 byte 本身只有这 256 个值
- Short / Long:默认也缓存 -128 ~ 127,但 Long 的缓存行为在部分 JDK 版本中不保证启用(依赖实现)
- Character:只缓存 Unicode 值 0 ~ 127(即 ASCII 字符区)
-
Boolean:仅缓存
true和false两个静态实例 - Float / Double:无缓存——浮点精度和取值范围太大,缓存无实际意义
为什么 == 比较有时 true、有时 false?
这不是设计目的,而是缓存带来的副作用:
-
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();集合做 key 或 value 判断时,尤其不能依赖 ==。
缓存范围可以调整吗?
仅 Integer 支持有限调整:
- 下限 -128 固定不可改
- 上限可通过 JVM 参数
-XX:AutoBoxCacheMax=200扩大(如设为 200) - 不推荐随意修改——可能破坏跨环境一致性,且多数业务无需超出 127
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











