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

Java 常量池深度解析:一道讓人抓狂的面試題

     編輯:Java 相關知識

面試題:輸出結果是什麼?

public class IntegerTest {
    public static void main(String[] args) {
        objPoolTest();
    }

    public static void objPoolTest() {
        Integer i1 = 40;
        Integer i2 = 40;
        Integer i3 = 0;
        Integer i4 = new Integer(40);
        Integer i5 = new Integer(40);
        Integer i6 = new Integer(0);

        System.out.println("i1==i2\t" + (i1 == i2));
        System.out.println("i1==i2+i3\t" + (i1 == i2 + i3));
        System.out.println("i4==i5\t" + (i4 == i5));
        System.out.println("i4==i5+i6\t" + (i4 == i5 + i6));
    }
}

輸出結果:

i1==i2	true
i1==i2+i3	true
i4==i5	false
i4==i5+i6	true

為什麼會這樣?核心在於 IntegerCache

Java 為了效能,對基本類型的包裝類實作了對象池機制。以 Integer 為例,編譯器會將 Integer i1 = 40; 轉換為 Integer i1 = Integer.valueOf(40);。

Integer.valueOf() 內部實現(JDK 8)

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

IntegerCache 是一個靜態內部類,在類加載時預先建立 [-128, 127] 範圍內的 Integer 實例緩存(長度 256)。

逐行解析

表達式結果原因
i1 == i2true40 在緩存範圍內,valueOf 返回同一個緩存實例,引用相同。
i1 == i2 + i3truei2 + i3 觸發拆箱,變為 int 運算(40 + 0 = 40),再與 i1 比較時 i1 也拆箱為 int,比較的是基本類型值。
i4 == i5falsenew Integer(40) 每次都在堆上建立新物件,不走緩存,引用不同。
i4 == i5 + i6true右側 i5 + i6 拆箱為 int 運算,左側 i4 也拆箱,比較基本類型值 40 == 40。

延伸思考:若將 40 改為 400?

i1==i2	false
i1==i2+i3	true
i4==i5	false
i4==i5+i6	true

因為 400 超出緩存範圍,Integer.valueOf(400) 每次都 new Integer(400),故 i1、i2 引用不同。

最佳實踐建議

  • 比較值請用 .equals():避免引用比較陷阱。
  • 避免不必要的自動裝箱/拆箱:在高效能循環中優先使用基本類型 int。
  • 了解緩存範圍可調整:-XX:AutoBoxCacheMax=size 可擴大上限(預設 127),但無法調整下限 -128。

總結

Integer 常量池是 Java 效能優化的經典案例。理解 valueOf 與 new 的差異、自動拆箱在 == 比較中的行為,是寫出正確且高效能 Java 代碼的基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved