先看一段代碼:
integer1 = Integer.valueOf(4);
integer2 = 4;
System.out.println(integer1 == integer2);
integer1 = 4;
integer2 = 4;
System.out.println(integer1 == integer2);
integer1 = 129;
integer2 = 129;
System.out.println(integer1 == integer2);
輸出結(jié)果為:
true
true
false
這是為何呢钾唬?
在 Java 5 中十办,為 Integer 的操作引入了一個新的特性,用來節(jié)省內(nèi)存和提高性能嗅绰。整型對象在內(nèi)部實現(xiàn)中通過使用相同的對象引用實現(xiàn)了緩存和重用舍肠,上面的規(guī)則適用于整數(shù)區(qū)間 -128 到 +127。
這種 Integer 緩存策略僅在自動裝箱(autoboxing)的時候有用窘面,使用構(gòu)造器創(chuàng)建的 Integer 對象不能被緩存翠语。所以一下代碼輸出結(jié)果是false:
// 沒有自動裝箱
Integer integer1 = new Integer(3);
Integer integer2 = 3;
System.out.println(integer1 == integer2);
Java 編譯器把原始類型自動轉(zhuǎn)換為封裝類的過程稱為自動裝箱(autoboxing),這相當于調(diào)用 valueOf 方法
Integer a = 10; //this is autoboxing
Integer b = Integer.valueOf(10); //under the hood
我們來看看 valueOf 的源碼:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
在創(chuàng)建新的 Integer 對象之前會先在 IntegerCache.cache 中查找财边。有一個專門的 Java 類來負責 Integer 的緩存肌括。IntegerCache 是 Integer 類中一個私有的靜態(tài)類。我們來看看這個類酣难,有比較詳細的文檔谍夭,可以提供我們很多信息。
/**
* 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 {@code -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) {
try {
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);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
Javadoc 詳細的說明這個類是用來實現(xiàn)緩存支持憨募,并支持 -128 到 127 之間的自動裝箱過程慧库。最大值 127 可以通過 JVM 的啟動參數(shù) -XX:AutoBoxCacheMax=size 修改。緩存通過一個 for 循環(huán)實現(xiàn)馋嗜。從小到大的創(chuàng)建盡可能多的整數(shù)并存儲在一個名為 cache 的整數(shù)數(shù)組中齐板。這個緩存會在 Integer 類第一次被使用的時候被初始化出來。以后葛菇,就可以使用緩存中包含的實例對象甘磨,而不是創(chuàng)建一個新的實例(在自動裝箱的情況下)。
實際上在 Java 5 中引入這個特性的時候眯停,范圍是固定的 -128 至 +127济舆。后來在 Java 6 中,最大值映射到 java.lang.Integer.IntegerCache.high莺债,可以使用 JVM 的啟動參數(shù)設(shè)置最大值滋觉。這使我們可以根據(jù)應用程序的實際情況靈活地調(diào)整來提高性能。是什么原因選擇這個 -128 到 127 這個范圍呢齐邦?因為這個范圍的整數(shù)值是使用最廣泛的椎侠。 在程序中第一次使用 Integer 的時候也需要一定的額外時間來初始化這個緩存。
這種緩存行為不僅適用于Integer對象措拇。我們針對所有整數(shù)類型的類都有類似的緩存機制我纪。
- 有 ByteCache 用于緩存 Byte 對象
- 有 ShortCache 用于緩存 Short 對象
- 有 LongCache 用于緩存 Long 對象
- 有 CharacterCache 用于緩存 Character 對象
Byte,Short,Long 有固定范圍: -128 到 127浅悉。對于 Character, 范圍是 0 到 127趟据。除了 Integer 可以通過參數(shù)改變范圍外,其它的都不行术健。