public static void main(String[] args) {
Integer p = 10000;
Integer q = 10000;
System.out.println(p == q); // false ❌
System.out.println(p.equals(q)); // true ✅
}
結論:比較包裝類數值必須使用 equals(),絕不可用 ==。
JDK 源碼 java.lang.Integer.IntegerCache 靜態內部類:
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
int h = 127;
String prop = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (prop != null) {
try {
int i = Integer.parseInt(prop);
i = Math.max(i, 127);
h = Math.min(i, Integer.MAX_VALUE - (-low) - 1);
} catch (NumberFormatException ignored) {}
}
high = h;
cache = new Integer[(high - low) + 1];
for (int k = 0, j = low; k < cache.length; k++) {
cache[k] = new Integer(j++);
}
// [-128, 127] 必須緩存 (JLS 5.1.7)
assert high >= 127;
}
private IntegerCache() {}
}
-XX:AutoBoxCacheMax=<size> 調整上限public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Integer p = 10000; 等價於 Integer p = Integer.valueOf(10000);new Integer(10000) 創建新對象== 比較引用地址,自然為 falseInteger a = 100; // 緩存範圍內
Integer b = 100;
System.out.println(a == b); // true ✅ (同一緩存對象)
Integer c = 200; // 緩存範圍外
Integer d = 200;
System.out.println(c == d); // false ❌ (不同對象)
| 類型 | 緩存範圍 | 配置參數 |
|---|---|---|
| Byte | 全範圍 [-128, 127] (全部緩存) | 無 |
| Short | [-128, 127] | -XX:AutoBoxCacheMax |
| Long | [-128, 127] | -XX:AutoBoxCacheMax |
| Character | [\u0000, \u007F] (0-127) | 無 |
| Integer | [-128, 127] | -XX:AutoBoxCacheMax |
注意:Float、Double 不緩存,每次裝箱必創建新對象。
equals():p.equals(q)int 別用 Integer,避免裝箱拆箱開銷與陷阱AutoBoxCacheMaxInteger 緩存機制是 JVM 優化自動裝箱性能的設計,但也引入了引用比較與值比較語義不一致的經典陷阱。理解緩存範圍、valueOf() 語義、自動裝箱行為,堅持「值比較用 equals,引用比較用 ==」,是避坑關鍵。