漫話:如何給女朋友解釋為什么Java 中"1000==1000"為false,而"100==100"為true?
- public static 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);
- }
以上代碼,輸出結(jié)果為:
- true
- false

動(dòng)拆裝箱
首先,我們在介紹自動(dòng)拆裝箱之前,修改一下上面的代碼,把變量的類型從Integer改為int,重新執(zhí)行以上代碼:
- public static 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);
- }
輸出結(jié)果為:
- true
- true
那么,int和Integer有啥區(qū)別呢?
int是基本數(shù)據(jù)類型,而Integer是包裝類。
因?yàn)镴ava是一種面向?qū)ο笳Z言,很多地方都需要使用對象而不是基本數(shù)據(jù)類型,如在集合中元素必須是對象類型的。
所以,Java種就給所有基本類型提供了對應(yīng)的包裝類,而int對應(yīng)的包裝類就是Integer。
有了基本數(shù)據(jù)類型和包裝類,就需要在他們之間進(jìn)行轉(zhuǎn)換,把基本類型轉(zhuǎn)成包裝類的過程就做裝箱,反之,叫做拆箱。
在Java SE5中,為了減少開發(fā)人員的工作,Java提供了自動(dòng)拆箱與自動(dòng)裝箱功能。
自動(dòng)裝箱: 就是將基本數(shù)據(jù)類型自動(dòng)轉(zhuǎn)換成對應(yīng)的包裝類。
自動(dòng)拆箱:就是將包裝類自動(dòng)轉(zhuǎn)換成對應(yīng)的基本數(shù)據(jù)類型。
在我們最開始的例子中,我們使用Integer integer1 = 100;定義并初始化一個(gè)變量。
這時(shí)候就涉及到一次自動(dòng)裝箱。因?yàn)?00是基本類型int,而需要把他賦值給包裝類型對象integer1,這時(shí)候就進(jìn)行了一次自動(dòng)裝箱。
Integer integer1 = 100; 其實(shí)是 Integer i = new Integer(10);的簡化寫法,就是因?yàn)镴ava中提供了自動(dòng)裝箱的功能。
自動(dòng)裝箱的緩存機(jī)制
Java SE的自動(dòng)拆裝箱還提供了一個(gè)和緩存有關(guān)的功能。
為了節(jié)省內(nèi)存和提升性能,Java給多個(gè)包裝類型提供了緩存機(jī)制,可以在自動(dòng)裝箱過程中,把一部分對象放到緩存中,實(shí)現(xiàn)了對象的復(fù)用。
如Byte、Short、Integer、Long、Character等都支持緩存。
對于Integer,其內(nèi)部有一個(gè)IntegerCache的內(nèi)部類。他會(huì)對整數(shù)值在-128 至 +127期間的對象進(jìn)行緩存。這個(gè)緩存會(huì)在Integer類第一次被使用的時(shí)候被初始化出來。以后,就可以使用緩存中包含的實(shí)例對象,而不是創(chuàng)建一個(gè)新的實(shí)例(在自動(dòng)裝箱的情況下)。
也就是說,當(dāng)我們對一個(gè)值在-128 至 +127期間的數(shù)字進(jìn)行自動(dòng)裝箱時(shí),并不是每次都新建一個(gè)對象,而是直接從緩存中取出一個(gè)緩存對象。
==比較的是什么
知道了自動(dòng)裝箱和其緩存機(jī)制,那么我們接下來看一下,當(dāng)我們代碼中使用==比較兩個(gè)對象的時(shí)候,比較的到底是什么?
很多人會(huì)認(rèn)為,對于整數(shù)類型,比較的當(dāng)然是整數(shù)的值了,但是其實(shí)不是的。
Java中的==,比較的時(shí)對象的地址,如果兩個(gè)對象的地址是同一個(gè),那么就返回true,否則返回false。
所以,因?yàn)橛辛俗詣?dòng)裝箱、因?yàn)橛辛司彺鏅C(jī)制,因?yàn)?=比較的是地址。
所以,當(dāng)對-128 至 +127中的兩個(gè)Interger進(jìn)行比較的時(shí)候,因?yàn)槎际菑木彺嬷腥〕鰜淼耐粋€(gè)對象,所以對象的地址是一樣的,就返回了true。
而對于1000,因?yàn)椴辉诰彺娣秶鷥?nèi),所以每次會(huì)新建對象,所以就會(huì)返回false。
但是需要注意的是,只有在自動(dòng)裝箱的時(shí)候才會(huì)有緩存機(jī)制,在構(gòu)造函數(shù)中是和緩存無關(guān)的,如以下代碼:
- Integer integer1 = new Integer(100);
- Integer integer2 = new Integer(100);
- System.out.println(integer1 == integer2);
輸出結(jié)果為
- false
關(guān)于作者:漫話編程,是一個(gè)通過漫畫+音頻的形式講解枯燥的編程知識(shí)的公眾號(hào)。致力于讓編程變得更有樂趣。
本文轉(zhuǎn)載自微信公眾號(hào)「漫話編程」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系漫話編程公眾號(hào)。