1. 程式人生 > >Java基礎之int和Integer有什麼區別

Java基礎之int和Integer有什麼區別

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

2 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變數指向的是java常量池中的物件,而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 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);
}

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

3.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
4 基本解析
4.1 自動裝箱:將基本資料型別重新轉化為物件
    public class Test {  
        public static void main(String[] args) {  
            //宣告一個Integer物件
            Integer num = 9;

            //以上的宣告就是用到了自動的裝箱:解析為:Integer num = new Integer(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 深入解析
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)。 
  加大對簡單數字的重利用,Java定義在自動裝箱時對於值從–128到127之間的值,它們被裝箱為Integer物件後,會存在記憶體中被重用,始終只存在一個物件。 
而如果超過了從–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));
    }
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() {}
    }