奇怪的Java題:為什麼1000 == 1000返回為False,而100 == 100會返回為True?
阿新 • • 發佈:2019-01-08
這是我們今天要討論的話題,因為我覺得它非常的有趣。
如果你執行如下程式碼:
1 2 3 4 |
Integer
a = 1000 ,
b = 1000 ;
System.out.println(a
== b); //1
Integer
c = 100 ,
d = 100 ;
System.out.println(c
== d); //2
|
你會得到以下執行結果:
1 2 |
false
true
|
我們知道,如果兩個引用指向同一個物件,那麼==就成立;反之,如果兩個引用指向的不是同一個物件,那麼==就不成立,即便兩個引用的內容是一樣的。因此,結果就會出現false。
這是非常有趣的地方。如果你檢視Integer.java類,你會找到IntegerCache.java這個內部私有類,它為-128到127之間的所有整數物件提供快取。
這個東西為那些數值比較小的整數提供內部快取,當進行如此宣告時:
1 |
Integer
c = 100 ;
|
它的內部就是這樣的:
1 |
Integer
i = Integer.valueOf( 100 );
|
如果我們觀察valueOf()類函式,我們可以看到
1 2 3 4 5 |
public
static
Integer valueOf( int
i) {
if
(i >= IntegerCache.low && i
return
IntegerCache.cache[i + (-IntegerCache.low)];
return
new
Integer(i);
}
|
如果值在-128到127之間,它就會返回該快取的例項。
因此。。。
1 |
Integer
c = 100 ,
d = 100 ;
|
兩者指向同樣的物件。
這就是為什麼這段程式碼的結果為true了:
1 |
System.out.println(c
== d);
|
現在你可能會問,為什麼會為-128到127之間的所有整數設定快取?
這是因為在這個範圍內的小數值整數在日常生活中的使用頻率要比其它的大得多,多次使用相同的底層物件這一特性可以通過該設定進行有效的記憶體優化。你可以使用reflection API任意使用這個功能。
執行下面的這段程式碼,你就會明白它的神奇所在了。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public
static
void
main(String[] args) throws
NoSuchFieldException, IllegalAccessException {
Class
cache = Integer. class .getDeclaredClasses()[ 0 ];
//1
Field
myCache = cache.getDeclaredField( "cache" );
//2
myCache.setAccessible( true ); //3
Integer[]
newCache = (Integer[]) myCache.get(cache); //4
newCache[ 132 ]
= newCache[ 133 ];
//5
int
a = 2 ;
int
b = a + a;
System.out.printf( "%d
+ %d = %d" ,
a, a, b); //
}
|