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

Java Integer 自動裝箱導致 == 比較行為差異深度解析

     編輯:Java 綜合教學

Java 中 equals 與 == 的關鍵差異:Integer 快取機制陷阱

自 JDK 5.0 引入自動裝箱/拆箱機制後,Integer i = 127 這類寫法變得普遍。然而,許多開發者發現 == 比較在某些數值範圍內返回 true,超出範圍卻返回 false,而 equals() 始終正確。本文深入剖析其背後的整數快取機制。

現象重現

public class IntegerCacheDemo {
    public static void main(String[] args) {
        // 測試案例 1:-128 到 127 範圍內
        Integer x1 = 127;
        Integer y1 = 127;
        System.out.println("127 == 127 : " + (x1 == y1));        // true
        System.out.println("127 equals : " + x1.equals(y1));      // true

        // 測試案例 2:超出快取範圍
        Integer x2 = 128;
        Integer y2 = 128;
        System.out.println("128 == 128 : " + (x2 == y2));        // false
        System.out.println("128 equals : " + x2.equals(y1));      // true

        // 直接 new 物件永不相等
        Integer x3 = new Integer(127);
        Integer y3 = new Integer(127);
        System.out.println("new 127 == : " + (x3 == y3));        // false
    }
}

核心原理:IntegerCache 內部類

查看 JDK 原始碼 java.lang.Integer,發現靜態內部類 IntegerCache:

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // 可透過 -XX:AutoBoxCacheMax= 調整上限,預設 127
        int h = 127;
        String integerCacheHighProp = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighProp != null) {
            try {
                int i = parseInt(integerCacheHighProp);
                i = Math.max(i, 127);
                h = Math.min(i, Integer.MAX_VALUE);
            } catch (NumberFormatException nfe) {
                // 忽略非法值
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for (int k = 0; k < cache.length; k++) {
            cache[k] = new Integer(j++);
        }
    }

    private IntegerCache() {}
}

自動裝箱時,Integer.valueOf(int) 會被呼叫:

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

關鍵結論

比較方式行為建議
==比較物件參考位址。
快取範圍內 (-128 ~ 127) 返回同一物件 → true
超出範圍或 new Integer() → false
嚴禁用於包裝類型數值比較
equals()比較數值內容。
無論快取與否,數值相等皆返回 true
標準做法,但需注意空指針
Objects.equals()空值安全的內容比較推薦最佳實踐 (JDK 7+)

其他包裝類型同樣擁有快取

  • Byte:全範圍快取 (-128 ~ 127)
  • Short:-128 ~ 127
  • Long:-128 ~ 127
  • Character:0 ~ 127 (Unicode BMP 範圍)
  • Boolean:僅兩個單例 TRUE、FALSE
  • Float/Double:無快取 (浮點數精度問題)

最佳實踐總結

  1. 永遠使用 Objects.equals(a, b) 或 a.equals(b) 比較包裝類型數值 (前者空值安全)
  2. 避免在邏輯判斷中依賴自動裝箱的快取行為
  3. 大量建立相同數值的 Integer 物件時,優先使用 Integer.valueOf() 利用快取減少記憶體壓力
  4. 若確需調整快取上限,可啟動參數 -XX:AutoBoxCacheMax=2000 (僅影響上限,下限固定 -128)

一行程式碼驗證快取範圍

IntStream.range(-130, 130).forEach(i -> 
    System.out.printf("%4d : %b%n", i, Integer.valueOf(i) == Integer.valueOf(i))
);

輸出將清晰顯示 -128 ~ 127 為 true,其餘為 false。

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