Integer.valueOf(int)是自动装箱的实际入口,参数在[-128,127]时从IntegerCache.cache取缓存对象,否则new创建;拆箱调用intValue(),null时抛NPE;字节码可验证编译器自动插入对应方法调用。

直接看 JDK 源码里的 Integer.valueOf(int) 方法和内部静态类 IntegerCache,就能搞清缓存机制和自动拆装箱的底层逻辑。关键不在语法糖,而在编译后实际调用哪段代码、对象从哪儿来。
Integer.valueOf() 是自动装箱的实际入口
写 Integer i = 100; 看似简单,编译器会把它转成 Integer i = Integer.valueOf(100);。这个方法就是自动装箱的真正实现:
- 参数
i在[-128, 127]范围内 → 从缓存数组IntegerCache.cache中取已有对象 - 超出该范围 → 调用
new Integer(i)创建新对象 - 所以
==比较时,小数字可能为true(同一缓存对象),大数字一定为false(不同堆地址)
IntegerCache 类定义了缓存的边界与结构
它位于 Integer 类内部,是私有静态类,核心字段包括:
-
static final int low = -128;—— 缓存下界,固定值 -
static final int high;—— 上界,默认 127,但可通过 JVM 参数-XX:AutoBoxCacheMax=200扩展 -
static final Integer[] cache;—— 实际缓存数组,索引偏移为i + 128(即 -128 存在 index 0) - 静态块中完成数组初始化,首次使用时才加载,节省内存
自动拆箱本质是调用 xxxValue() 方法
当执行 int x = i;(i 是 Integer 类型),编译器实际插入的是 i.intValue():
- 如果
i为null,调用intValue()会立即抛出NullPointerException - 这说明自动拆箱不是“安全操作”,必须确保包装类实例非空
- 所有包装类的拆箱都类似:
Long.longValue()、Boolean.booleanValue()等
验证方式:反编译 class 文件最直观
写一个测试类,编译后用 javap -c 查看字节码:
-
Integer a = 127;→ 字节码含invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer; -
int b = a;→ 字节码含invokevirtual java/lang/Integer.intValue()I - 没有
new Integer()或intValue()显式调用?那是编译器帮你补的


















