1. 程式人生 > >淺析Java自動裝箱和拆箱

淺析Java自動裝箱和拆箱

  最近在面試的時候,面試官提了一個很有趣的問題,如果這樣定義:

  int a = 1; Integer b = 1;你覺得a ==b?還是怎麼樣?如果換成1000呢?

  當時我沒有回答的出來,按照常規的思維,我覺得Integer是一個物件,int乃是基本的資料型別,所以我覺得這兩者應該是不等吧?因為==比較的是兩個是否為同一個物件,但是驗證之後才發現事實不是這麼回事。

  於是我刨根問底發現,造成這樣的原因是Java的自動拆箱的問題,而Java 1.5之前是需要我們手動遷移拆箱的,所以按照本來的思維判斷是沒錯的,那這個到底是怎麼一個過程呢?根據問題查詢答案:

   Integer b = 1;

  當我們這樣定義的時候,其實已經執行了自動拆箱,b = Integer.valueOf(1); b = Integer.intValue(); 所以b = 1,是int型別的

  當Integer b = 1000時,其實也是一樣的過程。

  但是如果換成Integer a = 1;Integer b = 1;  Integer c = 1000; Integer d = 1000;這樣得出的結果會是一樣嗎?一開始我覺得這樣不是一樣的嗎?一樣會執行自動拆箱的啊?但是結果又令我受益匪淺,這兩個的結果竟然不相等。一個為true,一個為false

  那麼造成這樣的原因是什麼呢?原來Integr包裝類會預設快取-127-128的數值在常量池中,而超出這個的不會快取,所以會出現false。但是如果又換成Integer a = new Integer(1);Integer b = new Integer(1);這樣呢?我原來以為這個不就是一樣的嗎?但是結果卻是另一個,因為這樣的操作沒有涉及到自動拆箱,所以這兩個是引用不同的物件,所以是false。

 那麼自動裝箱呢?又是怎麼回事?其實是反著進行:   

List<Integer> list = new ArrayList<Integer>();
list.add(2);
list.add(3);
list.stream().forEach(x->System.out.println(x));

上面的這個例子就是,如果沒有自動裝箱的話,在編譯期間應該會報錯。

Java的自動裝箱給我們帶來了很多的便利的,但是使用的時候要注意,避免出現下面的情況:

Integer a = 0;
for(int i = 0;i<10;i++){
a+=i;
}

這樣會造成建立不必要的物件。那在實際使用的時候應該使用int還是Integer就看個人需要了,int的預設值為0,而Integer為null。

Java中除了這個有意思之外,不可變的String也是很有意思的,比如它的intern()方法,後面再繼續理解,其實造成我們不敢確認是因為我們對常量池的理解不夠深入,需要慢慢來學習。