自動裝箱拆箱是 JDK 1.5 引入的語法糖,極大簡化了基本型別與包裝類轉換,但也引入了經典面試陷阱。本文深度剖析 Integer.valueOf() 快取機制、== 比較行為、算術運算觸發拆箱等核心知識點。
int → Integer),調用 Integer.valueOf(int)Integer → int),調用 Integer.intValue()public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
// IntegerCache 內部類
static final int low = -128;
static final int high = 127; // 可透過 -XX:AutoBoxCacheMax 調整上限
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 i1 = 100; // 裝箱 → valueOf(100) → 快取
Integer i2 = 100; // 快取同一對象
Integer i3 = 200; // 裝箱 → valueOf(200) → new Integer(200)
Integer i4 = 200; // 新對象
System.out.println(i1 == i2); // true 同一快取對象
System.out.println(i3 == i4); // false 不同 new 對象
System.out.println(i1 == 100); // true 100 是 int,觸發拆箱比較數值
System.out.println(i3 == 200); // true 同理拆箱比較數值
System.out.println(i1.equals(i2)); // true 比較數值
System.out.println(i3.equals(i4)); // true 比較數值
| 表達式 | 行為 | 結果 |
|---|---|---|
| 包裝類 == 包裝類 | 比較引用地址 | 快取範圍內 true,否則 false |
| 包裝類 == 基本型別 | 觸發拆箱,比較數值 | 數值相等則 true |
| 包裝類.equals(包裝類) | 比較數值(已重寫) | 數值相等則 true |
| 算術運算(+ - * /) | 自動拆箱為基本型別運算 | 結果為基本型別 |
Byte、Short、Long:全範圍快取(-128~127)Character:0~127 快取Boolean:TRUE、FALSE 兩個單例Float、Double:無快取(浮點數值無限,不可快取)equals() 或拆箱後用 ==Long sum = 0L; sum += i; 每次裝箱拆箱),改用基本型別-XX:AutoBoxCacheMax=3000 可擴大 Integer 快取上限(下限固定 -128)