先看現象吧java
執行下面的代碼及輸出結果:bash
int a = 1;
Integer b = 1;
Integer c = new Integer(1);
System.out.println(a==b);//true
System.out.println(a==c);//true
System.out.println(b==c);//false
複製代碼
一般你們對此的解釋是,==對於基本類型來講比較的是值,對於引用類型來講比較的是引用,即指向的對象的內存地址。這樣解釋沒錯,b==c結果爲false毋庸置疑,由於兩個都是引用類型。可是爲何a==b(a==c)一個是基本類型一個是引用類型,比較的時候仍是值比較呢?網絡
這個時候咱們不妨把.java源文件編譯後的.class文件使用反編譯工具反編譯成源碼,看看虛擬機內部是如何處理a==b的。工具
.class文件使用jd-gui反編譯後的:ui
int a = 1;
Integer b = Integer.valueOf(1);
Integer c = new Integer(1);
System.out.println(a == b.intValue());
System.out.println(a == c.intValue());
System.out.println(b == c);
複製代碼
看到這想必你們都明白了吧,其實基本類型a和引用類型b比較時,引用類型b調用自身的intValue()方法獲取Integer實際表示的int類型的值,即a == b.intValue()仍是兩個int類型的變量進行值比較。符合上述:==對於基本類型來講比較的是值,對於引用類型來講比較的是引用,即指向的對象的內存地址。spa
說到這,還要解釋下爲何兩個引用類型的值同樣而引用不同以及基本變量爲何是值比較。code
其實基本變量int a在內存裏只有一份,保存在棧(保存基本類型的變量數據及引用類型的引用)中,Integer b和Integer c中的int值都指向棧中同一個int,不會從新在棧中建立相同的int值。cdn
而對於Integer b和Integer c,其實例是保存在堆(保存全部new出來的對象)中,雖然表示的int值相同,可是在堆中有兩份,每次new都會在堆中開闢一片空間保存new的內容,故Integer b和Integer c分別在兩片不一樣的內存空間存儲,因此指向的內存地址不一樣。對象
JDK中Integer.valueOf()源碼:blog
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
複製代碼
瞭解原理是弄清問題的關鍵,像這樣的問題之後還多着呢。不懂的時候能夠敲敲代碼,而後反編譯,看看虛擬機是怎麼處理的,看看原理翻翻源碼,問題也就迎刃而解了。
(封面圖片來源於網絡,侵權請聯繫刪除)