一、何为128陷阱
Java中Integer类型在使用==比较时的特殊行为------128陷阱,解释了当数值在-128到127范围内,由于valueOf方法的缓存机制导致地址相同,比较为真;超出这个范围则新分配内存,地址不同,比较为假。
可以预测一下下面程序的输出结果:
答案在最后后面!
二、造成该现象的原因
让我们追寻到 Integer 数据类型的 valueOf 方法的源码:
原因就是:Integer 的 valueOf 方法当中,存储着一个 cache 数组,该数组相当于一个缓存,范围在 -128~127 闭区间。
cache数组初始化的源码:
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
h = Math.max(parseInt(integerCacheHighPropValue), 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
// Load IntegerCache.archivedCache from archive, if possible
CDS.initializeFromArchive(IntegerCache.class);
int size = (high - low) + 1;
// Use the archived cache if it exists and is large enough
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
for(int i = 0; i < c.length; i++) {
c[i] = new Integer(j++);
}
archivedCache = c;
}
cache = archivedCache;
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
当在该范围中进行自动装箱的时候,直接返回该值的内存地址(即 cache 数组的地址),所以在 -128~127 之间的数值用 == 进行比较时结果是相等(true),相当于比较的是同一元素的内存地址。不在该范围的数,需要开辟一个新的内存空间,此时内存地址就不相同了,所以返回结果是不相等(false)。
注意:如果对象是 new 出来的(如下),那么就不会存在128陷阱。原因是 new 出来的对象,内存地址都是不同的,比较的就不是同一个对象了。