今天發現一個挺詭異的問題,先來看看下面這段代碼:
public class Test {public static void main(String[] args) {
Integer a = 1000;
Integer b = 1000;
System.out.println("a==b : " + (a == b));
System.out.println("a.equals(b) : " + a.equals(b));
}
}
這段代碼的輸出結果是這樣的:
a==b : false
a.equals(b) : true
對於基本類型,以及基本類型的比較,我一直都是用“==”來進行比較的。一直沒注意這個問題,今天遇到了嚇一大跳。慶幸過去的程序中用“==”沒出現問題。把源碼拖出來看了一下,明白了,解釋如下:
平常我們使用Integer a = xxx;的時候,Integer類實際上是調用的是public static Integer valueOf(int i)方法。這個方法是這樣的。
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);
}
從上面代碼可以看出,當進行賦值操作時,Java將這個值分爲兩個區間來處理,即:
i 屬於[-128, 127]的時,返回IntegerCache.cache[i + offset];
i 屬於上面範圍以外時,返回new Integer(i)。
上面實例程序中,賦值超出[-128, 127]返回,所以返回爲new Integer(1000),而“==”比較是比較內存地址,那麼返回值肯定爲FALSE。
至此上面陳述的詭異問題就解開了。
但是Java爲什麼要這樣分區間處理呢,這不是使勁兒把我們往誤區裏勾引嗎?爲此我測試了這樣一個程序:賦值在[-128, 127]之間時。
public class Test {public static void main(String[] args) {
Integer a = 10;
Integer b = 10;
System.out.println("a==b : " + (a == b));
System.out.println("a.equals(b) : " + a.equals(b));
}
}
這段代碼的輸出結果是這樣的:
a==b : truea.equals(b) : true
爲什麼出現這種現象呢?這就要問IntegerCache.cache[i + offset]了,跟蹤進去代碼如下:
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
也就是說,當賦值在[-128, 127]區間時,Java是從同一個數據中取出同一個對象,即內存地址一樣,所以“==”操作返回TRUE;
那麼猜測Java這樣做的目的,可能[-128, 127]區間比較常用,這個區間內的Integer對象也作爲靜態變量初始化完成,這樣直接返回對象可以提高效率。
爲了防止不小心掉入這樣的陷阱,對於基本類型的比較,用“==”;而對於基本類型的封裝類型和其他對象,應該調用public boolean equals(Object obj)方法(複雜對象需要自己實現equals方法)。