Java中自動裝箱與拆箱詳解

自Java 5後引入了自動裝箱和自動拆箱機制,自動裝拆箱的出現主要是爲了解決基本數據類型跟其對應的包裝類之間相互轉換的問題,本文將從以下幾個方面詳解自動裝箱跟拆箱:

  • 自動裝拆箱的定義及原理
  • 自動裝拆箱發生的場合
  • 忽略自動裝拆箱可能會帶來的影響

自動裝拆箱的定義及原理

Java是一門面向對象的語言,但是基本數據類型並不是對象,因此基本數據類型能夠進行的操作很少,爲了彌補這一不足,Java爲每個基本數據類型配備了相對應的包裝類,有了包裝類,可以將基本數據類型當成包裝類來操作,但是包裝類跟基本數據之間總是免不了相互轉換,在Java 5之前,兩者在轉換時需要我們手動添加代碼,比較麻煩,隨着Java的發展成熟,Java 5後出現了自動裝箱跟拆箱,能夠自動實現基本數據類型與其對應包裝類的轉換,使得我們的代碼更加簡單簡潔。
定義:

自動裝箱是將基本數據類型轉換成包裝類的過程(如int轉換成Integer對象),自動拆箱反之,是將包裝類轉換成基本數據類型的過程。

原理:

自動裝箱時編譯器調用valueOf()方法將基本類型值轉換成對象,自動拆箱時,編譯器通過調用類似intValue(),doubleValue()這類的方法將對象轉換成基本類型值。

自動裝拆箱發生的場合

自動裝拆箱發生的場合總結起來分以下2種情況:

1.賦值時

Integer iObject = 6;//自動裝箱,在Java5之前必須寫成Integer iObject = Integer.valueOf(6)。
int i = iObject;//自動拆箱,在Java5之前必須寫成int i = iObject.intValue()。

在對Integer類型的變量直接賦值時會發生自動裝箱;將Integer對象賦值給int時會發生自動拆箱。當賦值大於127時,Integer每賦值一次都會產生一個新的Integer對象。如 Integer iObject3 = 129和Integer iObject4 = 129是兩個不同的對象,二者不指向同一個引用。

2.調用方法,傳遞對象類型參數時
比如我們不能直接在集合中放入基本類型值,因爲集合只接收對象類型。我們可以將基本類型的值轉換成對象,然後將這些轉換的對象放入集合中。以ArrayList爲例:

 ArrayList<Integer> list = new ArrayList<Integer>();
 list.add(1);
 list.add(2);

整型數默認爲int類型,使用Arraylist的add()方法時,int類型被自動裝箱成Integer對象。

但是ArrayList的remove方法,它有remove(index)和remove(Object)兩種重載,此時可能我們會有疑惑,在這裏會發生自動裝箱嗎?答案是不會。當方法重載時,傳入的該是什麼類型就是什麼類型,不會發生自動裝拆箱。
如下代碼:


public class Test {
    public void autoBoxingTest(int i){
        System.out.println("這是傳入int類型參數的方法");
    }
    public void autoBoxingTest(Integer integer){
        System.out.println("這是傳入Integer類型的方法");
    }

    public static void main(String[] args) {
        Test test = new Test();
        int i = 3;
        test.autoBoxingTest(i);//控制檯輸出“這是傳入int類型參數的方法”,說明int並沒有被自動裝箱成Integer。

        //手動將int裝箱成Integer類型
        Integer iObject = i;
        test.autoBoxingTest(iObject);//控制檯輸出“這是傳入Integer類型的方法”。
    }

}

忽略自動裝拆箱可能會帶來的影響

自動裝拆箱是編譯器幫我們自動完成的事情,但是如果我們不瞭解自動裝拆箱的原理,那麼可能會給我們帶來一些不必要的麻煩,比如:
1.int類型如果未初始化,它的默認值爲0,但是Integer類型如果未初始化,它的初始值爲null,當我們使用時可能會拋出NullPointerException的錯誤。如下代碼:iObject未初始化,因此在自動拆箱時會找不到值。

 Integer iObject ;
        if (iObject>60){
            System.out.println("考試成績合格");
        }

2.自動裝箱有一個問題,那就是在一個循環中進行自動裝箱操作的情況,如下面的例子就會創建多餘的對象,影響程序的性能。

Integer sum = 0;
 for(int i=1000; i<5000; i++){
   sum = sum+i;
}

這段程序的運行過程是:sum爲Integer類型,sum=sum+i時,首先將sum自動拆箱成int類型跟i相加,然後相加完成後sum又自動裝箱成Integer對象,每相加一次,就會產生一個Integer對象。 在上面的循環中會創建4000個無用的Integer對象,在這樣龐大的循環中,會降低程序的性能並且加重了垃圾回收的工作量。
因此在編程時,需要注意到這一點,正確地聲明變量類型,避免因爲自動裝箱引起的性能問題。

發佈了22 篇原創文章 · 獲贊 23 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章