Java Integer 128 陷阱与自动拆装箱全解析
·
一、核心知识点拆解
1. 包装类的核心作用
Java 8 种基本数据类型(如 int)不是对象,无法参与泛型、集合等面向对象场景,包装类(如 Integer)就是为基本类型提供 “对象化包装”,让基本类型能以对象形式使用。
2. 自动拆装箱(语法糖)
自动拆装箱是编译器帮我们简化手动转换的操作,底层还是调用了核心方法:
- 自动装箱(int → Integer):
Integer i = 10;→ 编译器翻译为Integer i = Integer.valueOf(10); - 自动拆箱(Integer → int):
int a = i;→ 编译器翻译为int a = i.intValue();
3. IntegerCache 缓存机制(128 陷阱的根源)
Integer 类内部有一个静态缓存类 IntegerCache,默认缓存 -128 ~ 127 范围内的 Integer 对象:
- 当调用
Integer.valueOf(i)时,若i在缓存范围:直接返回缓存中的对象; - 若
i超出范围:每次都会new Integer(i)创建新对象。
4. 128 陷阱实战验证
下面是完整的验证代码,包含注释和扩展场景(比如 new Integer、equals 对比):
java
运行
public class IntegerTrapDemo {
public static void main(String[] args) {
// 场景1:缓存范围内(127),== 比较对象地址 → true
Integer i = 127;
Integer j = 127;
System.out.println("i == j (127): " + (i == j)); // true
// 场景2:缓存范围外(128),== 比较对象地址 → false
Integer k = 128;
Integer l = 128;
System.out.println("k == l (128): " + (k == l)); // false
// 场景3:即使在缓存范围,new Integer 也会创建新对象 → false
Integer m = new Integer(127);
Integer n = new Integer(127);
System.out.println("m == n (new 127): " + (m == n)); // false
// 场景4:equals 比较数值(推荐)→ 始终true
System.out.println("k.equals(l) (128): " + k.equals(l)); // true
System.out.println("m.equals(n) (new 127): " + m.equals(n)); // true
// 场景5:包装类与基本类型比较(自动拆箱)→ 比较数值
Integer p = 128;
int q = 128;
System.out.println("p == q (128): " + (p == q)); // true
}
}
代码解释:
==对引用类型(Integer)比较的是对象内存地址,对基本类型(int)比较的是数值;equals()是 Integer 重写的方法,专门比较数值大小,不受缓存影响;- 包装类和基本类型用
==比较时,包装类会自动拆箱为基本类型,最终比较数值。
5. 避坑指南(开发必看)
- 比较数值优先用 equals ():无论数值是否在缓存范围,
equals()能保证比较的是数值,避免陷阱;👉 示例:if (num1.equals(num2)) { ... } - 避免手动 new Integer ():new 出来的对象不会走缓存,浪费内存且易出问题;
- 注意空指针风险:自动拆箱时如果 Integer 为 null,会抛出
NullPointerException:java
运行
Integer nullInt = null; int a = nullInt; // 运行时抛出 NPE
二、扩展知识点(面试加分)
- 其他包装类的缓存机制:
- Byte:缓存范围
-128 ~ 127(全部数值); - Short/Long:缓存范围
-128 ~ 127; - Character:缓存范围
0 ~ 127; - Float/Double:无缓存(数值范围太大,缓存无意义)。
- Byte:缓存范围
- 调整 Integer 缓存上限:可以通过 JVM 参数
-XX:AutoBoxCacheMax=N调整缓存上限(比如-XX:AutoBoxCacheMax=200),但下限-128不可改。
总结
- 128 陷阱本质:Integer 对
-128~127数值缓存对象,超出范围每次新建对象,导致==比较地址不一致; - 自动拆装箱:装箱调用
valueOf(),拆箱调用xxxValue()(如 intValue ()),是编译器语法糖; - 核心避坑:比较 Integer 数值用
equals(),避免 new Integer (),警惕拆箱时的空指针。
更多推荐




所有评论(0)