首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 裝箱拆箱深度解析:Integer 緩存機制與面試陷阱

     編輯:Java 相關知識

核心概念

  • 裝箱:基本類型 → 包裝類對象 (int → Integer),編譯器調用 Integer.valueOf(int)
  • 拆箱:包裝類對象 → 基本類型 (Integer → int),編譯器調用 Integer.intValue()
Integer a = 100;      // 自動裝箱:Integer.valueOf(100)
int b = new Integer(100); // 自動拆箱:new Integer(100).intValue()

Integer 緩存機制:關鍵源碼

public static Integer valueOf(int i) {
    final int offset = 128;
    if (i >= -128 && i <= 127) { // 緩存範圍 [-128, 127]
        return IntegerCache.cache[i + offset]; // 返回緩存對象
    }
    return new Integer(i); // 範圍外新建對象
}

經典面試題實戰分析

案例 1:new Integer vs 自動裝箱

public void m11() {
    Integer a = new Integer(100);
    Integer b = 100; // 自動裝箱
    System.out.println(a == b); // false
}

public void m12() {
    Integer a = new Integer(128);
    Integer b = 128;
    System.out.println(a == b); // false
}

結果:均為 false。new 總創建新對象,valueOf 可能走緩存,但兩者引用不同。

案例 2:雙 new Integer

public void m21() {
    Integer a = new Integer(100);
    Integer b = new Integer(100);
    System.out.println(a == b); // false
}

結果:false。兩次 new 創建不同對象。

案例 3:雙自動裝箱(核心考點)

public void m31() {
    Integer a = 100;
    Integer b = 100;
    System.out.println(a == b); // true!
}

public void m32() {
    Integer a = 128;
    Integer b = 128;
    System.out.println(a == b); // false
}

結果:100 → true,128 → false。

原因:均調用 valueOf。100 在緩存範圍內,返回同一緩存對象;128 超出範圍,各自新建對象。

案例 4:valueOf 顯式調用 vs 自動裝箱

public void m41() {
    Integer a = Integer.valueOf(100);
    Integer b = 100;
    System.out.println(a == b); // true
}

public void m42() {
    Integer a = Integer.valueOf(128);
    Integer b = 128;
    System.out.println(a == b); // false
}

結果同案例 3。字節碼證實自動裝箱本質就是調用 valueOf。


字節碼證據

// m31: Integer a = 100; Integer b = 100;
0: bipush 100
2: invokestatic Integer.valueOf:(I)Ljava/lang/Integer; // a
5: astore_1
6: bipush 100
8: invokestatic Integer.valueOf:(I)Ljava/lang/Integer; // b
11: astore_2
// 兩次調用 valueOf,100 走緩存,返回同一對象

// m32: Integer a = 128; Integer b = 128;
0: sipush 128
3: invokestatic Integer.valueOf:(I)Ljava/lang/Integer; // a
6: astore_1
7: sipush 128
10: invokestatic Integer.valueOf:(I)Ljava/lang/Integer; // b
13: astore_2
// 128 超出緩存,各自 new Integer(128)

其他包裝類緩存範圍

包裝類緩存範圍
Integer-128 ~ 127
Short-128 ~ 127
Byte-128 ~ 127 (全範圍)
Long-128 ~ 127
Character0 ~ 127
Booleantrue/false 兩個單例
Float/Double無緩存

最佳實踐與避坑指南

  1. 比較包裝類值務必用 .equals(),== 比較引用地址
  2. 集合存基本類型:自動裝箱存入,取出時自動拆箱,注意 NPE 風險
  3. 避免在循環中頻繁裝箱拆箱:如 Long sum = 0L; for(...) sum += i; 每次循環裝箱拆箱,改用基本類型 long sum = 0L;
  4. 數據庫查詢結果映射:MyBatis 等框架自動處理,但自寫 JDBC 時注意 ResultSet.getObject() 返回包裝類

總結

裝箱拆箱是 Java 語法糖,Integer.valueOf() 緩存機制是面試高頻考點。記住:

  • [-128, 127] 範圍內自動裝箱復用緩存對象
  • 超出範圍或 new 關鍵字創建新對象
  • 業務代碼永遠用 equals() 比較值
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved