// 片段 1
Integer a = new Integer(100);
Integer b = 100;
System.out.println(a == b); // false
// 片段 2
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true ← 驚訝?
// 片段 3
Integer a = 156;
Integer b = 156;
System.out.println(a == b); // false ← 又變了?
// 片段 4
Integer a = Integer.valueOf(100);
Integer b = 100;
System.out.println(a == b); // true
自動裝箱 `Integer b = 100;` 實際編譯為 `Integer.valueOf(100)`。查看 JDK 原始碼:
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
true。false。0: bipush 100
2: invokestatic #16 // Integer.valueOf
5: astore_1
6: bipush 100
8: invokestatic #16 // Integer.valueOf ← 自動裝箱也呼叫 valueOf
兩次呼叫 `valueOf(100)` 皆命中快取,故為同一物件。
| 片段 | 等價形式 | 結果 | 原因 |
|---|---|---|---|
| 1 | `new Integer(100)` vs `valueOf(100)` | false | 新物件 vs 快取物件 |
| 2 | `valueOf(100)` vs `valueOf(100)` | true | 雙方皆命中快取 |
| 3 | `valueOf(156)` vs `valueOf(156)` | false | 156 超出快取範圍,各自 new |
| 4 | `valueOf(100)` vs `valueOf(100)` | true | 同片段 2 |
拆箱 `int i = integerObj;` 編譯為 `integerObj.intValue()`。同理,`Long`、`Double` 等包裝類別皆有對應快取機制(`LongCache`、`Double` 無快取)。