天天看點

Interger對象源碼解析

今天研究了Interger的源碼,看了源碼後才知道根本,以前做過的關于interger的面試題都迎刃而解。

今天以面試題為引子

       Integer a5=128;

        Integer a6=128;

        Integer a7=127;

        Integer a8=127;

        Integer a9=new Integer(127);

        System.out.println(a5==a6);//false

        System.out.println(a7==a8);//true

        System.out.println(a9==a8);//false

        System.out.println(a9.equals(a8));在程式中運作 jdk1.7的環境下 是false,大家都知道 == 比對的位址的引用(不知道的話可以自行去搜尋下,網上很多的例子)

通過上面可以得到 a8 和 a9的數值相等 但是所引用的位址不是一樣的。為什麼呢?

首先虛拟機在編譯的過程中會把代碼優化一遍,也就是說上面的代碼可能不是我們想要的。先看一下編譯之後的代碼什麼樣子。

(class檔案反編譯之後的代碼)

       Integer a5 = Integer.valueOf(128);

        Integer a6 = Integer.valueOf(128);

        Integer a7 = Integer.valueOf(127);

        Integer a8 = Integer.valueOf(127);

        Integer a9 = new Integer(127);

        System.out.println(a5 == a6);

        System.out.println(a7 == a8);

        System.out.println(a9 == a8);

        System.out.println(a9.equals(a8));

大家可以看到 編譯器優化之後真正運作的代碼是這樣子的。=128 優化成了 Integer.valueOf(128).

然而  Integer.valueOf做了什麼事情呢?怎麼會 兩個128相比較會是不同的對象 兩個127 相比較就是相同的資料呢?

帶着疑問翻開了jdk源碼(大家可以用 intellij idea 直接檢視源碼)

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);

}

首先第一眼看過去這是個靜态的方法,通過Interger對象可以直接調用。看裡面的内容,第一次看的時候猜想了作者的意思,大約是判斷傳送過來的i的資料 是否在   IntegerCache.low  和 IntegerCache.high中間,如果在的話傳回一個IntegerCache.cache[i + (-IntegerCache.low)]。如果不在的話 new 一個對象。接着順藤摸瓜,看下上面這3個東西是什麼。

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() {}

}

研究了代碼發現,IntegerCache 是一個靜态的 私有的方法,裡面有很多的靜态對象,靜态是什麼?簡單的可以認為全局變量,誰都可以用,被緩存的資料。low 是 -128  high 預設是127 也可以配置,上面的意思是在程式啟動的時候,初始化一部分資料存在記憶體中,這些資料是什麼呢?

for(int k = 0; k < cache.length; k++)

            cache[k] = new Integer(j++);

    }

大家可以看到 這裡進行了一次for循環,裡面有個new 關鍵字(new 就是在堆中配置設定一塊記憶體),每次都建立一個對象,内  容是 low和high 中間的所有資料面也就是 (-128)到(127)中的資料,共255 Interger對象,建立了這些對象之後,吧他們的位址的引用存在了static final Integer cache[];  中,這是一個資料,而且是靜态的存在了緩存中,且不可變。

好了明白這些資料之後 再回過頭來看下上面的代碼所表達的意思。

Integer.valueOf(i)中,判斷傳送過來的i 是否在 -128 和127 中間,如果在就傳回return IntegerCache.cache[i + (-IntegerCache.low)];   不在就傳回 一個new 對象。

是以當

Integer.valueOf(128)的時候 比 127大 ,每次都是new 一個新的對象,

Integer.valueOf(127)的時候  等于127,就從緩存中拿出127的位址,不用建立一個對象了。

是以

System.out.println(a5==a6);//false

System.out.println(a7==a8);//true

每次new 的都是一個新的對象,不管緩存中是否存在,是以   System.out.println(a9==a8);//false

這是我看interger源碼中比較有感觸的地方,有不到和錯誤之處請說出來大家一起進步。

}

繼續閱讀