您現在的位置是:首頁 > 動作武俠首頁動作武俠
漫話:如何給女朋友解釋為什麼Java中"1000==1000"為false,而...
- 2023-01-16
為什麼要裝箱拆箱
因為Java是一種面嚮物件語言,很多地方都需要使用物件而不是基本資料型別,如在集合中元素必須是物件型別的。
publicstatic void main(String[] args) {
Integer integer1 = 100;
Integer integer2 = 100;
System。out。println(integer1 == integer2);
Integer integer3 = 1000;
Integer integer4 = 1000;
System。out。println(integer3 == integer4);
}
以上程式碼,輸出結果為:
true
false
動拆裝箱
首先,我們在介紹自動拆裝箱之前,修改一下上面的程式碼,把變數的型別從Integer改為int,重新執行以上程式碼:
publicstatic void main(String[] args) {
int integer1 = 100;
int integer2 = 100;
System。out。println(integer1 == integer2);
int integer3 = 1000;
int integer4 = 1000;
System。out。println(integer3 == integer4);
}
輸出結果為:
true
true
那麼,int和Integer有啥區別呢?
int是基本資料型別,而Integer是包裝類。
因為Java是一種面嚮物件語言,很多地方都需要使用物件而不是基本資料型別,如在集合中元素必須是物件型別的。
所以,Java種就給所有基本型別提供了對應的包裝類,而int對應的包裝類就是Integer。
有了基本資料型別和包裝類,就需要在他們之間進行轉換,把基本型別轉成包裝類的過程就做裝箱,反之,叫做拆箱。
在Java SE5中,為了減少開發人員的工作,Java提供了自動拆箱與自動裝箱功能。
自動裝箱: 就是將基本資料型別自動轉換成對應的包裝類。
自動拆箱:就是將包裝類自動轉換成對應的基本資料型別。
在我們最開始的例子中,我們使用Integer integer1 = 100;定義並初始化一個變數。
這時候就涉及到一次自動裝箱。因為100是基本型別int,而需要把他賦值給包裝型別物件integer1,這時候就進行了一次自動裝箱。
Integer integer1 = 100; 其實是 Integer i = new Integer(10);的簡化寫法,就是因為Java中提供了自動裝箱的功能。
自動裝箱的快取機制
Java SE的自動拆裝箱還提供了一個和快取有關的功能。
為了節省記憶體和提升效能,Java給多個包裝型別提供了快取機制,可以在自動裝箱過程中,把一部分物件放到快取中,實現了物件的複用。
如Byte、Short、Integer、Long、Character等都支援快取。
對於Integer,其內部有一個IntegerCache的內部類。他會對整數值在-128 至 +127期間的物件進行快取。這個快取會在Integer類第一次被使用的時候被初始化出來。以後,就可以使用快取中包含的例項物件,而不是建立一個新的例項(在自動裝箱的情況下)。
也就是說,當我們對一個值在-128 至 +127期間的數字進行自動裝箱時,並不是每次都新建一個物件,而是直接從快取中取出一個快取物件。
==比較的是什麼
知道了自動裝箱和其快取機制,那麼我們接下來看一下,當我們程式碼中使用==比較兩個物件的時候,比較的到底是什麼?
很多人會認為,對於整數型別,比較的當然是整數的值了,但是其實不是的。
Java中的==,比較的時物件的地址,如果兩個物件的地址是同一個,那麼就返回true,否則返回false。
所以,因為有了自動裝箱、因為有了快取機制,因為==比較的是地址。
所以,當對-128 至 +127中的兩個Interger進行比較的時候,因為都是從快取中取出來的同一個物件,所以物件的地址是一樣的,就返回了true。
而對於1000,因為不在快取範圍內,所以每次會新建物件,所以就會返回false。
但是需要注意的是,只有在自動裝箱的時候才會有快取機制,在建構函式中是和快取無關的,如以下程式碼:
Integer integer1 = new Integer(100);
Integer integer2 = new Integer(100);
System。out。println(integer1 == integer2);
輸出結果為
false