包装类中Byte、Short、Integer、Long缓存-128~127,Character缓存0~127,Boolean仅缓存TRUE/FALSE,Float/Double无缓存;比较值相等必须用equals或Objects.equals,禁用==。

基本类型没有缓存池,只有包装类才有缓存机制;所谓“共享”,是指同一数值在缓存范围内经 valueOf() 创建时复用同一个对象实例。规避 == 陷阱的关键不是绕开缓存,而是彻底放弃用 == 比较包装类的值是否相等。
哪些包装类有缓存?范围分别是多少
不是所有包装类都启用缓存,且范围各不相同:
-
Byte、Short、Integer、Long:默认缓存 -128 到 127(含),由各自内部静态缓存类(如
IntegerCache)实现 - Character:缓存 Unicode 值 0 到 127(即 ASCII 可见字符范围)
-
Boolean:仅两个实例
Boolean.TRUE和Boolean.FALSE,全部复用 -
Float、Double:无缓存,每次
valueOf()都新建对象,==几乎总为false
缓存只对 valueOf() 生效,new 和拆箱不参与
缓存行为完全绑定在 valueOf(int) 等静态工厂方法上,其他方式一律绕过:
-
Integer a = 127;→ 编译为Integer.valueOf(127)→ 命中缓存 → 复用对象 -
Integer b = new Integer(127);→ 强制新建对象 → 不进缓存 → 与 a 的==为false -
int c = a;→ 自动拆箱 → 转为基本类型再参与运算,此时a == c是合法的数值比较(因 a 拆箱为 int)
为什么 127 == 127 成立,而 128 == 128 不成立
这不是“128 特别”,而是缓存边界导致的对象复用差异:
-
Integer x = 127; Integer y = 127;→ 两次调用valueOf(127)→ 返回同一缓存数组中的同一元素 →x == y为true -
Integer m = 128; Integer n = 128;→ 两次调用valueOf(128)→ 超出缓存范围 → 各自新建对象 →m == n为false - 注意:
Integer.valueOf(128) == Integer.valueOf(128)在未调大缓存时仍为false,但若启动参数设为-Djava.lang.Integer.IntegerCache.high=200,则可能变为true—— 这进一步说明其不可靠
安全比较的唯一正确姿势
无论是否在缓存范围内,只要目标是判断“数值是否相等”,就必须避开 ==:
- 两个非 null 包装类:用
a.equals(b)(但需确保 a 不为 null) - 可能为 null 的任意包装类:统一用
Objects.equals(a, b)(内部已判空,推荐首选) - 混合类型比较(如
Integer与Long):必须显式转基本类型,例如a.longValue() == b.longValue() - 涉及算术或逻辑运算时,优先让 JVM 自动拆箱(如
if (a > 0)),避免手动调用xxxValue()引发 NPE

















