深入淺出了解“裝箱與拆箱”!

關(guān)注我

深入淺出了解“裝箱與拆箱”

每章一點(diǎn)正能量:每當(dāng)你想要放棄的時(shí)候膝晾,就想想是為了什么才一路堅(jiān)持到現(xiàn)在米辐。

前言

最近在回顧復(fù)習(xí)Java基礎(chǔ)中的一些知識(shí)點(diǎn)胸完,發(fā)現(xiàn)了一些以前見(jiàn)過(guò)但是沒(méi)有留意卻特別有意思的知識(shí)特性,比如這次想分享的Java中一個(gè)常見(jiàn)的特性:自動(dòng)裝箱與拆箱翘贮。這個(gè)知識(shí)點(diǎn)和特性其實(shí)在我們開(kāi)發(fā)過(guò)程中經(jīng)常會(huì)遇到赊窥。同時(shí)我們也會(huì)去使用一些基本數(shù)據(jù)類型或者是封裝數(shù)據(jù)類型,但是對(duì)于他們之間的一些轉(zhuǎn)換等特性可能不是特別清楚狸页。也可能出現(xiàn)在我們的面試中锨能。本章部分內(nèi)容從源碼中解讀一些自動(dòng)裝箱與拆箱的原理,以及會(huì)出現(xiàn)的一些陷阱已經(jīng)性能等芍耘。如有錯(cuò)誤還請(qǐng)大家及時(shí)指出~

本文已同步至 GitHub/Gitee/公眾號(hào)址遇,感興趣的同學(xué)幫忙點(diǎn)波關(guān)注~

問(wèn)題:

  • 基本數(shù)據(jù)類型與封裝數(shù)據(jù)類型有哪些區(qū)別?
  • 什么是裝箱斋竞?什么是拆箱倔约?
  • 裝箱和拆箱都是如何實(shí)現(xiàn)的?
  • 使用時(shí)需要注意哪些問(wèn)題坝初?

1.基礎(chǔ)知識(shí)回顧

  1. Java把內(nèi)存劃分成兩種:一種是棧內(nèi)存浸剩,另一種是堆內(nèi)存钾军。

  2. int是基本類型,直接存數(shù)值绢要;而 Integer是類吏恭,產(chǎn)生對(duì)象時(shí)用一個(gè)引用指向這個(gè)對(duì)象。

  3. 封裝類位于java.lang包中重罪。

  4. 封裝類是引用傳遞而基本類型是值傳遞

  5. 基本類型的變量和對(duì)象的引用變量都是在函數(shù)的棧內(nèi)存中分配 樱哼,而實(shí)際的對(duì)象是在存儲(chǔ)堆內(nèi)存中

1.1 基本數(shù)據(jù)類型和封裝類型的區(qū)別

我們來(lái)看下他們之間有哪些區(qū)別:


區(qū)別

八種基本數(shù)據(jù)類型分別是:byte、char蛆封、boolean唇礁、int、short惨篱、float、double围俘、long;
對(duì)應(yīng)的封裝類型分別是:Byte砸讳、Character、Boolean界牡、Integer簿寂、Short、Float宿亡、Double常遂、Long。

基本類型 封裝類型 字節(jié)長(zhǎng)度 默認(rèn)值
boolean Boolean 1 false
byte Byte 1 0
char Character 2 u0000
short Short 2 0
int integer 4 0
long Long 8 0l或0L
float Float 4 0.0f或0.0F
double Double 8 0.0

2. "==" 和 "equal()" 方法

在鞏固了上面的基礎(chǔ)知識(shí)點(diǎn)之后挽荠,我們?cè)賮?lái)看下另外的一個(gè)知識(shí)點(diǎn) "=="和"equal()" 這兩個(gè)判斷符在比較基本數(shù)據(jù)類型和封裝類型的時(shí)候會(huì)做的一些事情克胳。

" == ":比較的是基本數(shù)據(jù)類型,比較的是它們的值

"equals()": 比較的是引用數(shù)據(jù)類型圈匆,根據(jù)不同的數(shù)據(jù)類型調(diào)用不同的equals方法漠另。在特殊情況下可以重寫(xiě)equals方法。

a==b并不能判斷a等于b跃赚,而是判斷是否為同一個(gè)Object笆搓。如果我們要判斷他們的值怎么做呢?用equal或者Objects.equals()(JDK1.7之后新加 的語(yǔ)法)

Objects.equals有什么好處呢纬傲?

如果用a.equals(b) 如果a是null 的話满败,還會(huì)拋出空指針異常。但是用Objects.equals就沒(méi)有問(wèn)題叹括。因此我們?cè)谑褂靡妙愋偷臅r(shí)候需要注意算墨,當(dāng)我們?cè)谫x值的時(shí)候,兩個(gè)變量都是引用同一個(gè)Object领猾。

我們以 int與Integer 作為例子米同,看下"=="和"equal()"方法:

1)基本型和封裝類型進(jìn)行"=="運(yùn)算符的比較骇扇,封裝類型將會(huì)自動(dòng)拆箱變?yōu)榛拘秃笤龠M(jìn)行比較,因此Integer(0)會(huì)自動(dòng)拆箱為int類型再進(jìn)行比較面粮。

2)兩個(gè)Integer類型進(jìn)行"=="比較少孝,如果其值在-128至127,那么返回true熬苍,否則返回false, 這跟Integer.valueOf()的緩沖對(duì)象有關(guān)稍走,后面會(huì)說(shuō)。

3)兩個(gè)封裝類型進(jìn)行equals()比較柴底,首先equals()會(huì)比較類型婿脸,如果類型相同,則繼續(xù)比較值柄驻,如果值也相同狐树,返回true。

4)基本型封裝類型調(diào)用equals(),但是參數(shù)是基本類型鸿脓,這時(shí)候抑钟,先會(huì)進(jìn)行自動(dòng)裝箱,基本型轉(zhuǎn)換為其封裝類型野哭,再進(jìn)行3中的比較在塔。

3.什么是裝箱和拆箱

基本數(shù)據(jù)(Primitive)類型的自動(dòng)裝箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0開(kāi)始提供的功能拨黔。Java語(yǔ)言規(guī)范中說(shuō)道:在許多情況下包裝與解包裝是由編譯器自行完成的(在這種情況下包裝稱為裝箱蛔溃,解包裝稱為拆箱)。
通俗的理解:裝箱:基本類型轉(zhuǎn)換成封裝類型篱蝇, 拆箱:封裝類型轉(zhuǎn)換成基本類型 這么一個(gè)過(guò)程贺待。在上面有介紹八種基本類型和對(duì)應(yīng)的封裝類型。下面以Integer與int之間的轉(zhuǎn)換作為理解:

3.1 自動(dòng)裝箱(Autoboxing)


Integer a = 2; //Boxing

簡(jiǎn)單的理解:將2裝在一個(gè)箱子里态兴,這個(gè)箱子的類型是Integer 狠持。箱子這里面裝的數(shù)值就是2,我們就完成了一次裝箱操作瞻润。并把a(bǔ)指向2這個(gè)箱子喘垂。


Integer b = new Integer(2);//Boxing

顯示裝箱。生成一個(gè)新的箱子 new Integer(); 并且這個(gè)箱子的值為2.而且讓b指向這個(gè)箱子绍撞。

3.2 拆箱(Unboxing)

故名思議就是將對(duì)象重新轉(zhuǎn)化為基本數(shù)據(jù)類型


int v = a.intValue(); //Unboxing

簡(jiǎn)單的理解:將里面int的值取出來(lái)正勒。拆箱有個(gè)很典型的用法就是在進(jìn)行運(yùn)算的時(shí)候:因?yàn)閷?duì)象時(shí)不能直接進(jìn)行運(yùn)算的,而是要轉(zhuǎn)化為基本數(shù)據(jù)類型后才能進(jìn)行加減乘除傻铣。

例如:


Integer c = 5;
System.out.print(c--);//進(jìn)行計(jì)算時(shí)隱含的有自動(dòng)拆箱

4. 裝箱拆箱結(jié)合源碼分析

通過(guò)第四點(diǎn)我們知道裝箱拆箱的基本概念知識(shí)章贞,下面我們同樣以Integer 為例,進(jìn)入源碼里面看看里面的乾坤非洲。

我們首先看下Integer的大小鸭限。

4.1 Integer 大小

可以看出蜕径,其定義了Integer的最大值為231-1,最小值為-231败京。Integer的基本數(shù)據(jù)類型為int兜喻。

Integer大小

4.2 Integer中的valueOf()方法

再來(lái)看看Integer中的valueOf()方法。

Integer中的valueOf()

可以看出valueOf()方法是個(gè)靜態(tài)方法赡麦。當(dāng)傳進(jìn)來(lái)的變量值在一個(gè)區(qū)間之內(nèi)朴皆,直接用IntegerCache.cache[]數(shù)組里面的數(shù)返回,否則new一個(gè)新對(duì)象泛粹。

接著我們來(lái)看看IntegerCache類遂铡。其實(shí)也是會(huì)出現(xiàn)坑的一個(gè)地方。

4.3 其中存在的陷阱

接著來(lái)說(shuō)下Integer這兒的一個(gè)坑晶姊,也是比較有意思的地方扒接。

IntegerCache

初始化Integer后,IntegerCache會(huì)緩存[-128,127]之間的數(shù)據(jù)帽借,這個(gè)區(qū)間的上限可以配置珠增,取決于java.lang.Integer.IntegerCache.high這個(gè)屬性,這個(gè)屬性在VM參數(shù)里為-XX:AutoBoxCacheMax=2000進(jìn)行設(shè)置調(diào)整或者VM里設(shè)置-Djava.lang.Integer.IntegerCache.high=2000砍艾。所以Integer在初始化完成后會(huì)緩存[-128,max]之間的數(shù)據(jù)。cache屬于常量巍举,存放在java的方法區(qū)中脆荷。

同樣,在Long懊悯,Byte蜓谋,Short,我們也可以看到緩存炭分,其緩存數(shù)據(jù)長(zhǎng)度均是-128到127桃焕。這里不做展開(kāi)。

另外其他陷阱:
如:


System.out.println(Integer.valueOf(null));

Integer對(duì)象的值可以為null捧毛,所以編譯器檢查時(shí)不會(huì)出現(xiàn)檢查時(shí)異常观堂,但是在轉(zhuǎn)換成int的時(shí)候就會(huì)拋出空指針異常。

4. 例題分析

我們通過(guò)幾個(gè)經(jīng)典的問(wèn)題呀忧,來(lái)看看大家到底理解了裝箱與拆箱的知識(shí)點(diǎn)沒(méi)师痕。

  • new Integer(5) == 5?
  • new Integer(5) == new Integer(5) ?
  • Integer.valueOf(5) == Integer.valueOf(5)?
  • Integer.valueOf(5).intValue() == 5?
  • new Integer(5).equals(new Integer(5))?

4.1 問(wèn)題一:new Integer(5) == 5?

答案:true而账。 等號(hào)的左邊是一個(gè)Object右邊是一個(gè)數(shù)值胰坟,Object和數(shù)值怎么會(huì)相等的呢?Java的編譯器很聰明泞辐,它會(huì)自己去做裝箱和拆箱的操作笔横。這邊它將new Integer(5)做的是Unboxing竞滓,它會(huì)里面的value取出來(lái),這時(shí)候發(fā)現(xiàn)取出來(lái)的5等于右邊吹缔,所以就為true商佑。

4.2 問(wèn)題二:new Integer(5) == new Integer(5) ?

答案:false。 new Integer(5) 就是新建一個(gè)箱子涛菠,這個(gè)箱子的值就是5莉御。 == 是判斷這兩個(gè)箱子是不是同一個(gè)箱子,不是說(shuō)里面的值是不是一樣.所以是false俗冻。因?yàn)樗麄儾皇峭粋€(gè)箱子礁叔。

4.3 問(wèn)題三:Integer.valueOf(5) == Integer.valueOf(5)?

答案: true。 Integer.valueOf(5)它會(huì)返回一個(gè)箱子給我們迄薄,箱子里面的值是5琅关。但是在返回這個(gè)箱子給我們的時(shí)候,可能會(huì)新建一個(gè)新的箱子給我們讥蔽,也可能會(huì)使用現(xiàn)有的一個(gè)箱子給我們涣易。所以Integer.valueOf(5) == Integer.valueOf(5)。什么情況下才會(huì)相等呢冶伞?只有當(dāng)系統(tǒng)已經(jīng)將2這個(gè)箱子建立好了新症,并且緩存起來(lái)的情況下。會(huì)把箱子的引用同時(shí)發(fā)給等號(hào)的左邊與右邊响禽。這樣的情況徒爹,他們才會(huì)互相相等。Integer.valueOf() 是系統(tǒng)給我們分配的一個(gè)箱子芋类,我們發(fā)現(xiàn)隆嗅,每次調(diào)我們的箱子時(shí)候,系統(tǒng)都給了同一個(gè)箱子侯繁。這個(gè)我們的 Integer.valueOf(5) == Integer.valueOf(5)

但是: 可能為false胖喳。我們?cè)谏厦娼榻B過(guò),在low和high之間贮竟,它會(huì)返回一個(gè)系統(tǒng)已經(jīng)生產(chǎn)的cache丽焊,否則它會(huì)生產(chǎn)一個(gè)新的出來(lái)“用蹋看源碼可以看到low = -128 high = 127粹懒。所以當(dāng)它的值超過(guò)了區(qū)間后,它就會(huì)返回新的箱子顷级,所以就會(huì)為false凫乖。

我們不用5改用200試一試。

Integer.valueOf(200) == Integer.valueOf(200)

答案:false。 說(shuō)明系統(tǒng)對(duì)小的數(shù)字會(huì)使用系統(tǒng)分配的箱子帽芽,對(duì)于大的數(shù)字删掀,系統(tǒng)會(huì)重新new一個(gè)箱子。面試的時(shí)候导街,可以回答披泪,他們可能相等,也可能不相等搬瑰。是有系統(tǒng)決定的款票。

4.4 問(wèn)題四:Integer.valueOf(5).intValue() == 5?

答案: true泽论。 intValue()做了一個(gè)拆箱的操作艾少,將里面的值5取出來(lái),值5等于5翼悴,所以是true缚够。

4.5 問(wèn)題五:new Integer(5).equals(new Integer(5))?

答案:true。 這里我們沒(méi)有用==而是用equals鹦赎,equals判斷相等是判斷里面的值是不是相等谍椅,而不是判斷這個(gè)箱子是不是同一個(gè),所以我們的答案是true古话。我們來(lái)看看equals的源碼雏吭。判斷里面的值是不是相等。

equals

打印結(jié)果:

打印結(jié)果

文末

本章節(jié)主要簡(jiǎn)單介紹了自動(dòng)裝箱與拆箱的相關(guān)知識(shí)陪踩,希望對(duì)大家有所幫助~
今后我會(huì)在每張文章開(kāi)頭增加 每章一點(diǎn)正能量 思恐,文末增加5個(gè)編程相關(guān)的英語(yǔ)單詞 學(xué)點(diǎn)英語(yǔ)。希望大家和我一樣每天都能積極向上膊毁,一起學(xué)習(xí)一同進(jìn)步!

學(xué)點(diǎn)英語(yǔ)

  • AWT(Abstract Window Toolkit)抽象窗口工具
  • API(Application Programming Interface)應(yīng)用程序接口
  • AOP Aspect Oriented Programming(面向切面編程)基跑,可以 通過(guò)預(yù)編譯方式和運(yùn)行期動(dòng)態(tài)代理實(shí)現(xiàn)在不修改源代碼的情況下給程序動(dòng)態(tài)統(tǒng)一 添加功能的一種技術(shù)婚温。
  • BMP Bean-Managed Persistent(Bean管理的持久性),EJB中由 Bean自己負(fù)責(zé)持久性管理的方法媳否,Bean的內(nèi)容的同步(保存)需要自己編寫(xiě)代碼 實(shí)現(xiàn)栅螟。
  • I18N internationalization(國(guó)際化),這個(gè)單詞的長(zhǎng)度是20篱竭,然后取 其首尾字母力图,中間省略的字母剛好18個(gè)。

歡迎關(guān)注公眾號(hào):Coder編程
獲取最新原創(chuàng)技術(shù)文章和相關(guān)免費(fèi)學(xué)習(xí)資料掺逼,隨時(shí)隨地學(xué)習(xí)技術(shù)知識(shí)吃媒!

參考文章:

https://blog.csdn.net/u013309870/article/details/70229983

https://blog.csdn.net/jairuschan/article/details/7513045

https://www.cnblogs.com/dolphin0520/p/3780005.html

微信公眾號(hào)

推薦閱讀

一篇帶你讀懂TCP之“滑動(dòng)窗口”協(xié)議

帶你了解數(shù)據(jù)庫(kù)中JOIN的用法

帶你了解數(shù)據(jù)庫(kù)中g(shù)roup by的用法

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子赘那,更是在濱河造成了極大的恐慌刑桑,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件募舟,死亡現(xiàn)場(chǎng)離奇詭異祠斧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)拱礁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)琢锋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人呢灶,你說(shuō)我怎么就攤上這事吴超。” “怎么了填抬?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵烛芬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我飒责,道長(zhǎng)赘娄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任宏蛉,我火速辦了婚禮遣臼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拾并。我一直安慰自己揍堰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布嗅义。 她就那樣靜靜地躺著屏歹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪之碗。 梳的紋絲不亂的頭發(fā)上蝙眶,一...
    開(kāi)封第一講書(shū)人閱讀 52,785評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音褪那,去河邊找鬼幽纷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛博敬,可吹牛的內(nèi)容都是我干的友浸。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼偏窝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼收恢!你這毒婦竟也來(lái)了武学?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤派诬,失蹤者是張志新(化名)和其女友劉穎劳淆,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體默赂,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沛鸵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缆八。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片曲掰。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖奈辰,靈堂內(nèi)的尸體忽然破棺而出栏妖,到底是詐尸還是另有隱情,我是刑警寧澤奖恰,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布吊趾,位于F島的核電站,受9級(jí)特大地震影響瑟啃,放射性物質(zhì)發(fā)生泄漏论泛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一蛹屿、第九天 我趴在偏房一處隱蔽的房頂上張望屁奏。 院中可真熱鬧,春花似錦错负、人聲如沸坟瓢。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)折联。三九已至,卻和暖如春识颊,著一層夾襖步出監(jiān)牢的瞬間崭庸,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工谊囚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人执赡。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓镰踏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親沙合。 傳聞我的和親對(duì)象是個(gè)殘疾皇子奠伪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容