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 可以通過引數改變範圍外,其它的都不行。