今天跟大家聊一個有趣的話題,在Java中兩個Integer物件做比較時,會產生意想不到的結果。
例如:
Integer a = 100;
Integer b = 100;
System.out.println(a==b);
其執行結果是:true。
而如果改成下面這樣:
Integer a = 1000;
Integer b = 1000;
System.out.println(a==b);
其執行結果是:false。
看到這裡,懵了沒有?
為什麼會產生這樣的結果呢?
上面例子中的a和b,是兩個Integer物件。
而非Java中的8種基本型別。
8種基本型別包括:
Integer其實是int的包裝型別。
在Java中,除了上面的這8種型別,其他的型別都是物件,儲存的是參照,而非資料本身。
Integer a = 1000;
Integer b = 1000;
可能有些人認為是下面的簡寫:
Integer a = new Integer(1000);
Integer b = new Integer(1000);
這個想法表面上看起來是對的,但實際上有問題。
在JVM中的記憶體分佈情況是下面這樣的:
在棧中建立了兩個區域性變數a和b,同時在堆上new了兩塊記憶體區域,他們存放的值都是1000。
變數a的參照
指向第一個1000的地址。
而變數b的參照
指向第二個1000的地址。
很顯然變數a和b的參照不相等。
既然兩個Integer物件用==號,比較的是參照是否相等,但下面的這個例子為什麼又會返回true呢?
Integer a = 100;
Integer b = 100;
System.out.println(a==b);
不應該也返回false嗎?
物件a和b的參照不一樣。
Integer a = 1000;
Integer b = 1000;
其實正確的簡寫是下面這樣的:
Integer a = Integer.valueOf(1000);
Integer b = Integer.valueOf(1000);
在定義物件a和b時,Java自動呼叫了Integer.valueOf
將數位封裝成物件。
而如果數位在low和high之間的話,是直接從IntegerCache
快取中獲取的資料。
Integer類的內部,將-128~127之間的數位快取起來了。
也就是說,如果數位在-128~127,是直接從快取
中獲取的Integer物件。如果數位超過了這個範圍,則是new
出來的新物件。
文章範例中的1000,超出了-128~127的範圍,所以物件a和b的參照指向了兩個不同的地址。
而範例中的100,在-128~127的範圍內,物件a和b的參照指向了同一個地址。
所以會產生文章開頭的執行結果。
為什麼Integer類會加這個快取呢?
答:-128~127是使用最頻繁的數位,如果不做快取,會在記憶體中產生大量指向相同資料的物件,有點浪費記憶體空間。
Integer a = 1000;
Integer b = 1000;
如果想要上面的物件a和b相等,我們該怎麼判斷呢?
在Java中,如果使用==
號比較兩個物件是否相等,比如:a==b,其實比較的是兩個物件的參照是否相等。
很顯然變數a和b的參照,指向的是兩個不同的地址,參照肯定是不相等的。
因此下面的執行結果是:false。
Integer a = Integer.valueOf(1000);
Integer b = Integer.valueOf(1000);
System.out.println(a==b);
由於1000在Integer快取的範圍之外,因此上面的程式碼最終會變成這樣:
Integer a = new Integer(1000);
Integer b = new Integer(1000);
System.out.println(a==b);
如果想要a和b比較時返回true,該怎麼辦呢?
答:呼叫equals
方法。
程式碼改成這樣的:
Integer a = Integer.valueOf(1000);
Integer b = Integer.valueOf(1000);
System.out.println(a.equals(b));
執行結果是:true。
其實equals方法是Object類的方法,所有物件都有這個方法。
它的底層也是用的==號判斷兩個Object型別的物件是否相等。
不過Integer類對該方法進行了重寫:
它的底層會先呼叫Integer類的intValue方法獲取int型別的資料,然後再通過==號進行比較。
此時,比較的不是兩個物件的參照是否相等,而且比較的具體的資料是否相等。
我們使用equals方法,可以判斷兩個Integer物件的值是否相等,而不是判斷參照是否相等。
最近我建了新的技術交流群,打算將它打造成高質量的活躍群,歡迎小夥伴們加入。
我以往的技術群裡技術氛圍非常不錯,大佬很多。
Integer類中有快取,範圍是:-128~127
。
Integer a = 1000;
其實預設呼叫了Integer.valueOf
方法,將數位轉換成Integer型別:
Integer a = Integer.valueOf(1000);
如果數位在-128~127之間,則直接從快取中獲取Integer物件。
如果數位在-128~127之外,則該方法會new一個新的Integer物件。
我們在判斷兩個物件是否相等時,一定要多注意: