天天看點

Java自動裝箱與拆箱

  自動裝箱與拆箱機制在實際使用中非常常見,不過也特别容易出錯,部落客在面對下面一道題的時候自信滿滿,可還是沒有能夠全對,是以寫下這篇博文,給自己對自動裝箱與拆箱機制做一下知識鞏固,也給各位朋友做一下參考。

  首先有這樣一道題,給出下面代碼的輸出結果:

  運作結果:

  如果你看到這邊,答案都正确,而且沒有絲毫的疑問,那麼對于你來說這篇博文就此結束了,如果沒有,請繼續翻閱。

  首先從最基礎的開始講起,首先通過反編譯來看一看自動裝箱和拆箱的過程:

  首先看如下一段程式:

  可以看到Integer a=1實際上自動裝箱為Integer a = Integer.valueOf(1),而在進行a+b的時候可以看到進行了自動拆箱,将a拆箱為Integer.intValue();然後将a和b的int值相加,相加之後有進行了自動裝箱:Integer c=Integer.valueOf(3).

  接下來我們就可以上面題目中給出的 System.out.println(c==d);和System.out.println(e==f);他們分别的結果為true和false。

  知道Integer會緩存-128至127的朋友估計這兩條語句的輸出結果都能答對。

  如果沒有答對,請看解析:

  Integer c=3;會自動裝箱為Integer c = Integer.valueOf(3),那麼看一下valueOf方法的源碼:

  可以看到實際上Integer會緩存-128值127的内容,如果值在這個區間之内(比如c和d),那麼就會傳回IntegerCache中的引用,是以Integer c= Integer d = IntegerCache.cache[3+(–128)] = IntegerCache.cache[131], c和d是相等的。

  但是如果超過這個區間,比如e和f,則Integer e = new Integer(321); Integer f = new Integer(321);new出來的自然是在堆中新開辟的記憶體,兩份位址不同,自然e和f不同,也就是如果遇到這樣的情況:

  那麼輸出的結果是false(如果Integer m=2; Intger n=2則m和n相同)

  接着再說System.out.println(c==(a+b));

  我們看如下代碼:

  反編譯之後:

  可以看到實際在c==(a+b)的時候是執行拆箱機制,實際上就是在運算3==2+1,當然就是true咯。

  繼續說明: System.out.println(c.equals(a+b));

  同樣看一下c.equals(a+b)反編譯的結果(篇幅限制,隻截取部分相關的結果):

  可以看到a+b先拆箱為int再相加之後再裝箱為Integer型與c進行equals比較,那麼我們再看一下equals()方法的源碼:

  通過檢視源碼可知此條語句的輸出結果為true。

  最後來看一下System.out.println(g==(a+b));和System.out.println(g.equals(a+b));兩條語句。

  System.out.println(g==(a+b));由前面的推論可知最後g拆箱為long型,a+b為int型,基礎類型int可以自動更新為long,是以輸出為true。

  對于System.out.println(g.equals(a+b));可以看一下Long的equals()方法。

  對于(a+b)來說是Integer類型,是以傳回false.

  鑒于包裝類的“==”運算在不遇到算術運算的情況下不會自動拆箱,以及它們equals()方法不處理資料轉型的關系,部落客建議在實際編碼中要盡量避免這樣使用自動裝箱與拆箱機制。