奇怪的Java題:為什么128 == 128返回為False,而127 == 127會返回為True?
這是我們今天要討論的話題,因為我覺得它非常的有趣。
如果你運行如下代碼:
class A
{
public static void main(String[] args)
{
Integer a = 128, b = 128;
System.out.println(a == b);
Integer c = 127, d = 127;
System.out.println(c == d);
}
}
你會得到如下結果:
false
true
我們知道,如果兩個引用指向同一個對象,那么==就成立;反之,如果兩個引用指向的不是同一個對象,那么==就不成立,即便兩個引用的內容是一樣的。因此,結果就會出現false。
這是非常有趣的地方。如果你查看Integer. Java 類,你會找到IntegerCache.java這個內部私有類,它為-128到127之間的所有整數對象提供緩存。
這個東西為那些數值比較小的整數提供內部緩存,當進行如此聲明時:
Integer c = 127
它的內部就是這樣的:
Integer var3 = Integer.valueOf(127);
其實我通過將 A.class 文件反編譯后,代碼如下圖:
如果我們觀察valueOf()類函數,我們可以看到:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
如果值在-128到127之間,它就會返回該緩存的實例。
因此。。。
Integer c = 127, d = 127;
兩者指向同樣的對象。
這就是為什么下面這段代碼的結果為true了:
System.out.println(c == d);
現在你可能會問,為什么會為-128到127之間的所有整數設置緩存?
這是因為在這個范圍內的小數值整數在日常生活中的使用頻率要比其它的大得多,多次使用相同的底層對象這一特性可以通過該設置進行有效的內存優化。你可以使用reflection API任意使用這個功能。
運行下面的這段代碼,你就會明白它的神奇所在了。
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Class cache = Integer.class.getDeclaredClasses()[0];
Field myCache = cache.getDeclaredField("cache");
myCache.setAccessible(true);
Integer[] newCache = (Integer[]) myCache.get(cache);
newCache[132] = newCache[133];
int a = 2;
int b = a + a;
System.out.printf("%d + %d = %d", a, a, b); //
}
打印結果竟然是:
2 + 2 = 5
我們再次看一下反匯編代碼:
是不是又和上面的是同一個問題呢?
但是結果為什么是 2 + 2 = 5 呢?
我們繼續去看一下 Integer 源碼,去深入了解 Integer 緩存機制,下面截個圖:
根據源碼可以發現最后修改 Integer 緩存上限時候的方法有點小瑕疵。我們看看Api給我們怎么建議的一段話:
the size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
原來我們只需要:運行時設置 -XX:AutoBoxCacheMax=133 就OK。
來自:http://www.androidchina.net/6158.html