1. 程式人生 > >本型別與包裝(裝箱)型別的區別

本型別與包裝(裝箱)型別的區別

Java的型別分為兩部分,一個是基本型別(primitive),如int、double等八種基本資料型別;另一個是引用型別(reference type),如String、List等。而每一個基本型別又各自對應了一個引用型別,稱為包裝型別(或裝箱型別,boxed primitive)。裝箱基本型別中對應於int 、double、和boolean的是Integer、Double、Boolean。 基本型別與包裝型別的主要區別在於以下三個方面: 1、基本型別只有值,而包裝型別則具有與它們的值不同的同一性(identity)。這個同一性是指,兩個引用是否指向同一個物件,如果指向同一個物件,則說明具有同一性。(與此類似的還有等同性。)

來看一段程式碼:

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. Integer g = new Integer(0);  
  2. Integer h = new Integer(0);  
  3.               System.out.println(g==h)  
        Integer g = new Integer(0);
        Integer h = new Integer(0);
                System.out.println(g==h)
  • 1
  • 2
  • 3
以上程式碼,兩個物件雖然具有相同的值,但其引用指向的物件卻不相同,因此會輸出false。 再來看一段程式碼: [java]
view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. Integer a = 0;  
  2. Integer b = 0;  
  3. System.out.println(a==b);  
       Integer a = 0;
        Integer b = 0;
    System.out.println(a==b);</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre><br>
這個會輸出什麼呢?別急,再看一段程式碼: [java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. Integer d = 128;  
  2. Integer f = 128;  
  3. System.out.println(f==d);  
      Integer d = 128;
        Integer f = 128;
        System.out.println(f==d);
  • 1
  • 2
如果你沒有執行這兩段程式碼,就知道答案,那麼相信你對常量池有一定的瞭解了。 其實,當我們直接給一個Integer賦予一個int值的時候,它會呼叫一個valueOf()的方法。所以,如上程式碼就相當於: Integer a = Integer.valueOf(0); Integer的常量池是由-128至127組成。當我們給一個Integer賦的值在這個範圍之類時就直接會從快取返回一個相同的引用,所以a==b會輸出true。而超過這個範圍時,就會重新new一個物件。因此,f==d就會輸出一個false。 現在我們再來看一段程式碼: [java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. int e = 128;  
  2. Integer d = 128;  
  3. System.out.println(e==d);  
        int e = 128;
        Integer d = 128;
        System.out.println(e==d);
  • 1
  • 2
這個會輸出什麼呢?答案是true. 因為當在一項操作中混合使用基本型別與包裝型別時,包裝型別會自動拆箱。因此,e和d的比較其實就是int值的比較了。 2、基本型別只有功能完備的值,而包裝型別除了其對應的基本型別所有的功能之外,還有一個非功能值:null。

現在來看一段簡單的程式碼:

[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. static Integer i;  
  2. publicstaticvoid main(String[] args) {  
  3.     if(i == 128){  
  4.         System.out.println(”Unbelieveable~”);  
  5.     }  
  6. }  
 static Integer i;
    public static void main(String[] args) {
        if(i == 128){
            System.out.println("Unbelieveable~");
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
你認為會輸出什麼呢?不知道?自己執行一下~~~~ 其實這段程式碼並不能正確的執行,因為它會報一個NullPointException異常,為什麼?因為在定義i的時候,它是Integer類的一個引用,而i沒有初始化,就像所有物件引用一樣,如果沒有初始化那麼就賦一個null值。既然現在i是一個null,那麼上面已經提到,當混合使用基本型別與包裝型別時,包裝類會自動拆箱。現在i都沒有指向任何物件,因此拆箱的時候就會報一個NullPointException異常。 3、基本型別通常比包裝型別更節省時間與空間。 看如下程式碼: [java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. Long sum = 0L;  
  2. for(long i = 0;i<Integer.MAX_VALUE;i++){  
  3.     sum +=i;  
  4. }  
  5. System.out.println(sum);  
     Long sum = 0L;
    for(long i = 0;i&lt;Integer.MAX_VALUE;i++){
        sum +=i;
    }
    System.out.println(sum);</code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li></ul></pre><br>
毫無疑問,這段程式碼能正常執行,但是花費的時間會比較長。因為,在宣告sum變數的時候,一不小心宣告為Long,而不是long。這樣,在這個迴圈當中就會不斷地裝箱和拆箱,其效能也會明顯的下降。如果把Long改為long,那麼經過我的試驗,這段程式碼所花費的時間將只有原來的1/5. 經過這三個比較,貌似感覺基本型別已經完勝了包裝型別。但是在如下三個地方,包裝型別的使用會更合理: 1、作為集合中的元素、鍵和值。 2、在引數化型別中。比如:你不能這樣寫——ArryList<int>,你只能寫ArrayList<Integer>. 3、在進行反射方法的呼叫時。 總之,當可以選擇時候,基本型別是要優先於包裝型別。基本型別更加簡單、更加快速。 源自:http://blog.csdn.net/cynthia9023/article/details/17413375