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

Java 裝箱拆箱深度解析:Integer 緩存陷阱與面試必考 5 題

     編輯:Java 綜合教學

Java 裝箱拆箱深度解析:Integer 緩存陷阱與面試必考 5 題

自動裝箱(基本類型 → 包裝類)與拆箱(包裝類 → 基本類型)是 JDK 5 引入的語法糖。本文從字節碼層面揭示實現原理,深度剖析 IntegerCache 緩存機制,並通過 5 道經典面試題驗證掌握程度。

基本概念對照表

基本類型包裝類裝箱方法拆箱方法
intIntegerInteger.valueOf(int)Integer.intValue()
byteByteByte.valueOf(byte)Byte.byteValue()
shortShortShort.valueOf(short)Short.shortValue()
longLongLong.valueOf(long)Long.longValue()
floatFloatFloat.valueOf(float)Float.floatValue()
doubleDoubleDouble.valueOf(double)Double.doubleValue()
charCharacterCharacter.valueOf(char)Character.charValue()
booleanBooleanBoolean.valueOf(boolean)Boolean.booleanValue()

字節碼層面的真相

// 源碼
Integer i = 10;      // 裝箱
int n = i;           // 拆箱

// 反編譯字節碼
ICONST_10
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;  // 裝箱調用 valueOf
ASTORE 1
ALOAD 1
INVOKEVIRTUAL java/lang/Integer.intValue ()I                  // 拆箱調用 intValue
ISTORE 2

結論:裝箱本質調用 Wrapper.valueOf(),拆箱本質調用 Wrapper.xxxValue()。

IntegerCache 緩存機制源碼解析

public static Integer valueOf(int i) {
    if (i >= -128 && i <= IntegerCache.high)  // 默認高位 127
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

private static class IntegerCache {
    static final int low = -128;
    static final int high = 127;  // 可通過 -XX:AutoBoxCacheMax=N 調大
    static final Integer[] cache = new Integer[(high - low) + 1];
    static {
        for (int k = 0; k < cache.length; k++)
            cache[k] = new Integer(low + k);
    }
}

關鍵點:

  • 緩存範圍 [-128, 127],超出範圍每次 new Integer()
  • Byte/Short/Long/Character 同理緩存對應範圍
  • Float/Double 無緩存:浮點數在區間內個數無限,無法預緩存
  • Boolean:直接返回單例 TRUE/FALSE

面試必考 5 題實戰演練

題 1:Integer 緩存邊界

Integer i1 = 100, i2 = 100, i3 = 200, i4 = 200;
System.out.println(i1 == i2); // true  (緩存命中)
System.out.println(i3 == i4); // false (新對象)

題 2:Double 無緩存

Double d1 = 100.0, d2 = 100.0, d3 = 200.0, d4 = 200.0;
System.out.println(d1 == d2); // false
System.out.println(d3 == d4); // false

題 3:Boolean 單例

Boolean b1 = false, b2 = false, b3 = true, b4 = true;
System.out.println(b1 == b2); // true
System.out.println(b3 == b4); // true

題 4:new Integer vs 自動裝箱

Integer a = new Integer(100); // 每次 new,不走緩存
Integer b = 100;              // 走 valueOf,可能命中緩存
System.out.println(a == b);   // false (引用不同)
System.out.println(a.equals(b)); // true (值相等)

差異總結:① 不觸發裝箱 ② 效能上自動裝箱通常優於 new(緩存複用)

題 5:混合運算中的拆箱陷阱

Integer a=1, b=2, c=3, d=3, e=321, f=321;
Long g=3L, h=2L;

c == d                    // true  (緩存)
e == f                    // false (超出緩存)
c == (a + b)              // true  (a+b 觸發拆箱→int 運算→裝箱比較值)
c.equals(a + b)           // true  (拆箱運算後裝箱再 equals)
g == (a + b)              // true  (Long 拆箱為 long 比較數值)
g.equals(a + b)           // false (Integer 1+2=3 裝箱為 Integer,Long.equals(Integer) 返回 false)
g.equals(a + h)           // true  (a+h=3L 裝箱為 Long,Long.equals(Long) 返回 true)

核心規則:

  1. == 兩側均為包裝類引用 → 比較引用地址
  2. == 任一側為表達式(含算術運算)→ 觸發拆箱比較數值
  3. equals() 不進行類型轉換,Integer.equals(Long) 恆為 false

生產環境最佳實踐

  • ✅ 包裝類比較值統一用 equals() 或 顯式拆箱 intValue()
  • ✅ 高頻熱點路徑優先用基本類型,避免裝箱拆箱開銷
  • ✅ 集合存儲大量數字時,考慮 Trove/FastUtil 原始類型集合
  • ✅ 如需擴大緩存範圍,啟動參數 -XX:AutoBoxCacheMax=2000
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved