1. 引言
在牛客網上看到這樣一道題目,判斷一下打印的結果
public static void main(String[] args){
Integer i1 = 128;
Integer i2 = 128;
System.out.println(i1==i2);
Integer i3 = 100;
Integer i4 = 100;
System.out.println(i3==i4);
}
剛開始看到是,是這樣來判斷的:因爲 Integer i1 = 128 這條語句,Integer 會啓用自動裝箱功能,調用 Integer.valueOf 方法返回一個 Integer 對象,因此這四個對象應該指向不同的地址,所以打印的結果是兩個 false。但是在 eclipse 運行結果如下,爲什麼會這樣呢?
2. 分析
首先想到的就是 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);
}
從中可以看出,valueOf 方法首先會判斷 i 值是否在一個範圍內,如果是的話,會從 IntegerCache 的 cache(其實是一個用 final static 修飾的數組) 中返回 Integer 對象,如果不在這個範圍內,會創建一個新的 Integer 對象。那麼就看一下這個範圍是什麼吧。跟到 IntegerCache 類內部,可以看到它定義的兩個變量,low 爲 -128,high 還未定義。
static final int low = -128;
static final int high;
通過 ctrl+F 查找 high 是什麼時候創建的,發現是在一個靜態代碼塊裏面:
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
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;
}
從中可以看出,high 的值是由 h 決定的,h 一般爲 127。這說明,當 valueOf 傳入的參數值在 -128~127 之間,這些數值都會存儲在靜態數組 cache 中。因此,在 valueOf 方法裏,參數在 -128~127 之間,返回 Integer 對象的地址引用是一樣的,對於題目也有了正確的解答。
3. 總結
剛開始學編程時,如果碰到問題時,都是把報錯的信息賦值到百度或者谷歌上進行搜索,直接根據被人的踩坑經驗,按照他們給的步驟來解決問題,現在我又發現了一種更高效的解決方案 -- 直接看源碼,直接瞭解底層的實現,很快就可以解決問題了。所以,把自己的基礎打牢,勿以浮沙築高臺!