缓存机制仅影响对象复用,不改变数值语义;==比较不可靠因它比地址而非值,安全做法是统一用Objects.equals(a,b)。

理解包装类缓存机制的关键,是明白它只影响对象创建方式和内存复用,不改变“数值相等”的语义。真正要避免的陷阱,不是缓存本身,而是误把==当作数值比较工具。
缓存生效的三个前提条件
Integer等包装类的缓存不是自动触发的,必须同时满足:
- 使用
Integer.valueOf(int)或自动装箱(如Integer i = 100;) - 数值落在默认范围:Integer、Byte、Short、Long 是 -128 ~ 127;Character 是 0 ~ 127;Boolean 固定为 true/false 两个实例
- 没有调用已弃用的构造器(如
new Integer(100)),该方式永远绕过缓存
== 比较为什么不可靠
== 对包装类始终比较的是对象引用地址,不是数值大小。它的结果取决于是否命中缓存,而缓存行为又受数值范围、创建方式、JVM参数等多重因素影响:
-
Integer a = 127; Integer b = 127;→a == b为 true(共用缓存对象) -
Integer c = 128; Integer d = 128;→c == d为 false(各自新建对象) -
Integer e = new Integer(127); Integer f = Integer.valueOf(127);→e == f为 false(一个新对象,一个缓存对象)
安全比较的统一做法
无论数值大小、是否为空、是否在缓存范围内,都应采用语义明确、行为稳定的方式:
立即学习“Java免费学习笔记(深入)”;
- 判断“是否相等”:优先用
Objects.equals(a, b)(Java 7+),它内部先判空再调用equals(),零NPE风险 - 判断“谁大谁小”:用
a.compareTo(b)(返回负数/0/正数),或确保非空后解包:a.intValue() > b.intValue() - 集合键值或哈希场景:必须依赖
equals()和hashCode()的一致性,==完全不适用
关于缓存配置的务实提醒
虽然可通过-Djava.lang.Integer.IntegerCache.high=200扩大Integer缓存上限,但实际意义有限:
- 仅对Integer有效,其他包装类不可调
- 需JVM启动时设置,运行中无法更改
- 缓存对象常驻堆内存,盲目扩大可能增加GC压力,低配环境有OOM风险
- 无法根除逻辑隐患——只要代码里还存在
==比较包装类,就仍可能在边界值或不同JVM配置下出错


















