1. 程式人生 > >Integer快取池(IntegerCache)及整型快取池

Integer快取池(IntegerCache)及整型快取池

Integer 快取是 Java 5 中引入的一個有助於節省記憶體、提高效能的特性。

Integer中有個靜態內部類IntegerCache,裡面有個cache[],也就是Integer常量池,常量池的大小為一個位元組(-128~127)。JDK原始碼如下(摘自JDK1.8原始碼):

/**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the -XX:AutoBoxCacheMax=<size> option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

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

當建立Integer物件時,不使用new Integer(int i)語句,大小在-128~127之間,物件存放在Integer常量池中。

例如:Integer a = 10;

呼叫的是Integer.valueOf()方法,程式碼為:

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

這也是自動裝箱的程式碼實現。JAVA將基本型別自動轉換為包裝類的過程稱為自動裝箱(autoboxing)。

實際上在 Java 5 中引入這個特性的時候,範圍是固定的 -128 至 +127。後來在Java 6 後,最大值對映到 java.lang.Integer.IntegerCache.high,可以使用 JVM 的啟動引數設定最大值。(通過 JVM 的啟動引數 -XX:AutoBoxCacheMax=size 修改

快取通過一個 for 迴圈實現。從小到大的建立儘可能多的整數並存儲在一個名為 cache 的整數陣列中。這個快取會在 Integer 類第一次被使用的時候被初始化出來。以後,就可以使用快取中包含的例項物件,而不是建立一個新的例項(在自動裝箱的情況下)。


測試情況:

                int i = 10;
		int i1 = 10;
		Integer in1 = 10;
		Integer in2 = 10;
		Integer in3 = new Integer(10);
		Integer in4 = new Integer(10);
		Integer in5 = 199;
		Integer in6 = 199;
		
		System.out.println(i == i1);		// true
		System.out.println(i == in1);		// true
		System.out.println(i == in2);		// true
		System.out.println(i == in3);		// true
		
		System.out.println(in1 == in2);		// true
		System.out.println(in5 == in6);		// false
		
		System.out.println(in1 == in3);		// false
		
		System.out.println(in3 == in4);		// false

在 Boxing Conversion 部分的Java語言規範(JLS)規定如下:

如果一個變數 p 的值屬於:-128至127之間的整數(§3.10.1),true 和 false的布林值 (§3.10.3),’u0000′ 至 ‘u007f’ 之間的字元(§3.10.4)中時,將 p 包裝成 a 和 b 兩個物件時,可以直接使用 a == b 判斷 a 和 b 的值是否相等。

所有整數型別的類都有類似的快取機制:

有 ByteCache 用於快取 Byte 物件

有 ShortCache 用於快取 Short 物件

有 LongCache 用於快取 Long 物件

Byte,Short,Long 的快取池範圍預設都是: -128 到 127。可以看出,Byte的所有值都在快取區中,用它生成的相同值物件都是相等的。

所有整型(Byte,Short,Long)的比較規律與Integer是一樣的。

同時Character 物件也有CharacterCache 快取 池,範圍是 0 到 127。

除了 Integer 可以通過引數改變範圍外,其它的都不行。