Java包装类缓存机制默认缓存Integer、Byte、Short、Long的-128~127,Character的0~127,Boolean的TRUE/FALSE;仅valueOf()和自动装箱触发,new绕过缓存;比较须用equals()。

Java 包装类利用整型常量池缓存常用数值,核心是复用已创建的对象,避免重复分配内存。这个机制对 Integer、Byte、Short、Character、Boolean 有效,但原理和范围各不相同;其中 Integer 的缓存最典型、也最常被误用。
哪些值会被自动缓存?
不是所有整数都进池,只有特定范围的值在类加载时就预创建好,后续直接复用:
-
Integer:默认 -128 到 127(含),共 256 个对象;可通过 JVM 参数
-Djava.lang.Integer.IntegerCache.high=200扩大上限(最低仍为 -128) - Byte:固定缓存全部可能值,即 -128 ~ 127
- Short / Long:也缓存 -128 ~ 127,但超出该范围的行为不强制要求缓存(JVM 实现可选)
- Character:缓存 '\u0000' ~ '\u007F'(即 ASCII 0~127)
-
Boolean:只缓存两个静态实例
Boolean.TRUE和Boolean.FALSE - Float / Double:不缓存——浮点数值离散、不可穷举,缓存无意义
怎么触发缓存?关键看创建方式
缓存只在调用 valueOf() 或发生自动装箱时生效;用 new 构造器永远绕过缓存:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- ✅
Integer a = 100;→ 编译器转为Integer.valueOf(100),命中缓存 - ✅
Integer b = Integer.valueOf(100);→ 显式调用,同样命中 - ❌
Integer c = new Integer(100);→ 总是新建对象,c == a为false - ⚠️
Integer d = 200;→ 超出默认范围,valueOf(200)内部返回新对象,不共享
为什么不能用 == 比较包装类?
== 比的是引用地址,而缓存是否生效直接影响地址是否相同:
立即学习“Java免费学习笔记(深入)”;
-
Integer x = 127; Integer y = 127;→x == y是true(同一缓存对象) -
Integer m = 128; Integer n = 128;→m == n是false(两个独立对象) - 这种行为不稳定,容易引发隐蔽 bug,尤其在集合查找、条件判断中
- ✅ 正确做法:一律用
.equals()比较逻辑值,它先判空再比原始值,结果可靠
缓存不是万能的,别过度依赖
缓存本质是 JVM 启动时在方法区(或堆,视 JDK 版本)预分配的一组静态对象,目的是减少小整数频繁创建的开销:
- 它对性能提升有限——现代 JIT 编译器对简单装箱优化极强,实际差异微乎其微
- 扩大 Integer 缓存上限会增加类加载内存占用,且仅在启动时生效,运行中无法调整
- 不要为“省一个对象”去改 JVM 参数;应优先保证代码语义清晰、行为可预测
- 需要高性能数值计算时,尽量用基本类型(
int)而非包装类

















