Java包装类缓存机制由JVM自动启用,仅valueOf()和自动装箱生效;Integer/Byte/Short/Long缓存-128~127,Character缓存0~127,Boolean仅缓存TRUE/FALSE,Float/Double无缓存;比较必须用equals()。

Java 包装类通过 valueOf() 方法利用内置缓存机制复用对象,避免重复创建,从而显著降低内存占用和 GC 压力。核心不是“手动开启缓存”,而是只调用 valueOf()(或自动装箱),不使用 new 构造函数。
哪些包装类有缓存?范围分别是多少
并非所有包装类都缓存,且缓存策略各不相同:
-
Integer、Byte、Short、Long:默认缓存 -128 到 127(含)共 256 个值;其中只有 Integer 的上限可通过 JVM 参数
-XX:AutoBoxCacheMax=2000扩展(如设为 2000,则 -128~2000 全部缓存) - Character:缓存 \u0000 到 \u007F(即 0~127)的字符
-
Boolean:仅两个常量对象
Boolean.TRUE和Boolean.FALSE,每次valueOf(true)都返回同一引用 - Float / Double:不缓存(因浮点精度与取值连续性,缓存无意义),但依然必须用 valueOf() 而非 new——语义清晰、未来可优化、保持代码一致性
为什么 valueOf() 能省内存
以 Integer 为例,其内部 IntegerCache 是一个静态 final 数组,在类加载时就一次性创建好全部缓存对象。后续调用 Integer.valueOf(42) 时:
- 若 42 ∈ [-128, 127] → 直接返回数组中已有对象(地址复用)
- 若 42 ∉ 缓存范围 → 才执行
new Integer(42)创建新实例
而 new Integer(42) 每次都强制在堆上分配新空间,即使值相同,对象也互不相同,无法共享——这会快速堆积临时对象,加重 GC 负担。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
怎么写才能真正触发缓存
缓存只对特定调用方式生效,关键在于路径唯一性:
- ✅ 安全有效:
Integer i = Integer.valueOf(100);或Integer j = 100;(自动装箱,编译后等价于 valueOf) - ❌ 完全绕过:
Integer k = new Integer(100);(JDK 9+ 已标记@Deprecated,禁止使用) - ⚠️ 注意:即使数值在 -128~127 内,
new也绝不复用缓存对象;Integer.valueOf(100) == new Integer(100)恒为false
缓存带来的比较陷阱与正确做法
缓存会让小范围内的 == “碰巧”为 true,但这不是设计保证:
-
Integer a = 127; Integer b = 127;→a == b为true(同缓存对象) -
Integer c = 128; Integer d = 128;→c == d为false(各自新建)
因此,所有包装类值比较必须用 equals(),它先判空再比原始值,稳定可靠,不受缓存影响。把 == 当作值判断是典型隐患。

















