1. 程式人生 > 實用技巧 >int 和 Integer 有什麼區別

int 和 Integer 有什麼區別

1 Java兩種資料型別

1.1 Java兩種資料型別分類

(1)基本資料型別,分為boolean、byte、int、char、long、short、double、float;
(2)引用資料型別 ,分為陣列、類、介面。

1.2 Java為每個基本資料型別提供了封裝類

為了程式設計的方便還是引入了基本資料型別,但是為了能夠將這些基本資料型別當成物件操作,Java為每 一個基本資料型別都引入了對應的包裝型別(wrapper class),int的包裝類就是Integer,從Java 5開始引入了自動裝箱/拆箱機制,使得二者可以相互轉換。

基本資料型別: boolean,char,byte,short,int,long,float,double
封裝類型別:Boolean,Character,Byte,Short,Integer,Long,Float,Double

2 int與Integer的基本使用對比

  • Integer是int的包裝類;int是基本資料型別;
  • Integer變數必須例項化後才能使用;int變數不需要;
  • Integer實際是物件的引用,指向此new的Integer物件;int是直接儲存資料值 ;
  • Integer的預設值是null;int的預設值是0。

3 int與Integer的深入對比

(1)由於Integer變數實際上是對一個Integer物件的引用,所以兩個通過new生成的Integer變數永遠是不相等的(因為new生成的是兩個物件,其記憶體地址不同)。

Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false

(2)Integer變數和int變數比較時,只要兩個變數的值是向等的,則結果為true(因為包裝類Integer和基本資料型別int比較時,java會自動拆包裝為int,然後進行比較,實際上就變為兩個int變數的比較)

Integer i = new Integer(100);
int j = 100;
System.out.print(i == j); //true

(3)非new生成的Integer變數和new Integer()生成的變數比較時,結果為false。因為非new生成的Integer變數指向的是靜態常量池中cache陣列中儲存的指向了堆中的Integer物件,而new Integer()生成的變數指向堆中新建的物件,兩者在記憶體中的物件引用(地址)不同。

Integer i = new Integer(100);
Integer j = 100;
System.out.print(i == j); //false

(4)對於兩個非new生成的Integer物件,進行比較時,如果兩個變數的值在區間-128到127之間,則比較結果為true,如果兩個變數的值不在此區間,則比較結果為false

Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true

Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false

對於第4條的原因: java在編譯Integer i = 100 ;時,會翻譯成為Integer i = Integer.valueOf(100)。而java API中對Integer型別的valueOf的定義如下,對於-128到127之間的數,會進行快取,Integer i = 127時,會將127這個Integer物件進行快取,下次再寫Integer j = 127時,就會直接從快取中取,就不會new了。

public static Integer valueOf(int i){
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high){
        return IntegerCache.cache[i + (-IntegerCache.low)];
    }
    return new Integer(i);
}

4 自動裝箱和自動拆箱——解釋2(2)

4.1 自動裝箱:將基本資料型別重新轉化為物件

    public class Test {  
        public static void main(String[] args) {  
            // 宣告一個Integer物件,用到了自動的裝箱:解析為:Integer num = Integer.valueOf(9);
	        Integer num = 9;
        }  
    }  

9是屬於基本資料型別的,原則上它是不能直接賦值給一個物件Integer的。但jdk1.5後你就可以進行這樣的宣告,自動將基本資料型別轉化為對應的封裝型別,成為一個物件以後就可以呼叫物件所宣告的所有的方法。

4.2 自動拆箱:將物件重新轉化為基本資料型別

 public class Test {  
        public static void main(String[] args) {  
            / /宣告一個Integer物件
	        Integer num = 9;
            
            // 進行計算時隱含的有自動拆箱
		    System.out.print(num--);
        }  
    }  

因為物件時不能直接進行運算的,而是要轉化為基本資料型別後才能進行加減乘除。對比:

// 裝箱
Integer num = 10;
// 拆箱
int num1 = num;

5 深入解析Integer——解釋2(3/4)

5.1 問題描述

   public class Test {  
        public static void main(String[] args) {  
	        // 在-128~127 之外的數
            Integer num1 = 128;   
            Integer num2 = 128;           
            System.out.println(num1==num2);   //false
                        
            // 在-128~127 之內的數 
            Integer num3 = 9;   
            Integer num4 = 9;   
            System.out.println(num3==num4);   //true
        }  
    }  

解析原因:歸結於java對於Integer與int的自動裝箱與拆箱的設計,是一種模式:叫享元模式(flyweight)。
(1)加大對簡單數字的重利用,Java定義在自動裝箱時對於在-128~127之內的數值,它們被裝箱為Integer物件後,會存在記憶體中被重用,始終只存在一個物件。
(2)而如果在-128~127之外的數,被裝箱後的Integer物件並不會被重用,即相當於每次裝箱時都新建一個 Integer物件。

5.2 Integer原始碼解析

給一個Integer物件賦一個int值的時候,會呼叫Integer類的靜態方法valueOf,原始碼如下:

public static Integer valueOf(String s, int radix) throws NumberFormatException {
        return Integer.valueOf(parseInt(s,radix));
    }

/**
 * (1)在-128~127之內:靜態常量池中cache陣列是static final型別,cache陣列物件會被儲存於靜態常量池中。
 * cache數組裡面的元素卻不是static final型別,而是cache[k] = new Integer(j++),
 * 那麼這些元素是儲存於堆中,只是cache陣列物件儲存的是指向了堆中的Integer物件(引用地址)
 * 
 * (2)在-128~127 之外:新建一個 Integer物件,並返回。
 */
public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high) {
            return IntegerCache.cache[i + (-IntegerCache.low)];
        }
        return new Integer(i);
    }

IntegerCache是Integer的內部類,原始碼如下:

     /**
      * 快取支援自動裝箱的物件標識語義 -128和127(含)。
      * 快取在第一次使用時初始化。 快取的大小可以由-XX:AutoBoxCacheMax = <size>選項控制。
      * 在VM初始化期間,java.lang.Integer.IntegerCache.high屬性可以設定並儲存在私有系統屬性中
     */
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++) {
                cache[k] = new Integer(j++); // 建立一個物件
            }
        }

        private IntegerCache() {}
    }