一、核心知识点拆解

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. 避坑指南(开发必看)
  1. 比较数值优先用 equals ():无论数值是否在缓存范围,equals() 能保证比较的是数值,避免陷阱;👉 示例:if (num1.equals(num2)) { ... }
  2. 避免手动 new Integer ():new 出来的对象不会走缓存,浪费内存且易出问题;
  3. 注意空指针风险:自动拆箱时如果 Integer 为 null,会抛出 NullPointerException

    java

    运行

    Integer nullInt = null;
    int a = nullInt; // 运行时抛出 NPE
    

二、扩展知识点(面试加分)

  1. 其他包装类的缓存机制
    • Byte:缓存范围 -128 ~ 127(全部数值);
    • Short/Long:缓存范围 -128 ~ 127
    • Character:缓存范围 0 ~ 127
    • Float/Double:无缓存(数值范围太大,缓存无意义)。
  2. 调整 Integer 缓存上限:可以通过 JVM 参数 -XX:AutoBoxCacheMax=N 调整缓存上限(比如 -XX:AutoBoxCacheMax=200),但下限 -128 不可改。

总结

  1. 128 陷阱本质:Integer 对 -128~127 数值缓存对象,超出范围每次新建对象,导致 == 比较地址不一致;
  2. 自动拆装箱:装箱调用 valueOf(),拆箱调用 xxxValue()(如 intValue ()),是编译器语法糖;
  3. 核心避坑:比较 Integer 数值用 equals(),避免 new Integer (),警惕拆箱时的空指针。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐