開發中既然有基本類型和包裝類型,肯定有些時候要在它們之間進行轉換。把基本類型轉換成包裝類型的過程叫做裝箱(boxing)。反之,把包裝類型轉換成基本類型的過程叫做拆箱(unboxing)。
先看一段代碼
// 第一組
int a = 100;
Integer b = 100;
System.out.println( a == b ); // true
// 第二組
Integer a2 = 100;
Integer b2 = 100;
System.out.println( a2 == b2 ); // true
// 第三組
Integer a3 = 200;
Integer b3 = 200;
System.out.println( a3 == b3 ); // false
第一段代碼,基本類型和包裝類型進行 == 比較,這時候 b 會自動拆箱,直接和 a 比較值,所以結果爲 true。
第二段代碼,兩個包裝類型都被賦值爲了 100,這時候會進行自動裝箱,那 == 的結果會是什麼呢?引用數據類型進行==比較的時候,是不是進行的地址+值比較方式呢,那麼第二組的答案是false?但是,這次的結果卻是true。有點意外。
第三組代碼,還是兩個引用數據類型進行了==比較,好多人問,這不跟第二組一樣的嗎,都是連個引用類型比較,有什麼區別嗎,答案是true。但是真的嗎?運行代碼我們發現,這次答案是false。Why?
爲什麼?
最簡單的方式:看源碼。。。但是博主也是小白,對於源碼,我就不多做解釋,網上解釋的很清楚。
我們都知道,自動裝箱是通過 Integer.valueOf()
完成的,那我們就來看看這個方法的源碼吧。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
這段源碼看起來沒毛病,那麼毛病出在哪兒了呢,難不成是 IntegerCache 在作怪?你猜對了!
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
}
從這裏我們發現了問題了。-128 到 127 之間的數會從 IntegerCache 中取,然後比較,所以第二段代碼(100 在這個範圍之內)的結果是 true,而第三段代碼(200 不在這個範圍之內,所以 new 出來了兩個 Integer 對象)的結果是 false。
看完上面的分析之後,我們知道了:當需要進行自動裝箱時,如果數字在 -128 至 127 之間時,會直接使用緩存中的對象,而不是重新創建一個對象。
對於其他的引用數據類型大致情況相似,感興趣的可以研究一下。