前几天遇到一个很有意思的问题:
Integer a=100; Integer b=100; Integer c=200; Integer d=200; System.out.println(a==b); System.out.println(c==d);
刚开始我也有疑问,为什么会出这样的题?在我看来java中如果Integer不是new出Integer对象,而是直接赋值,这种情况就是在常量池中开辟出同一个空间来存储,所以a,b都指向常量池中的100,c,d都指向常量池中的200,所以都应该是true。
但实际结果是这样:
????
经大佬指点,我得到了答案。也了解了我之前想法的不合逻辑。
在用Integer直接赋值时,牵扯到自动装箱拆箱问题。装箱就是 自动将基本数据类型转换为包装器类型;拆箱就是 自动将包装器类型转换为基本数据类型。而自动装箱与拆箱是怎样实现的呢?通过查找发现:在装箱的时候自动调用的是Integer的valueOf方法。而在拆箱的时候自动调用的是Integer的intValue方法。
所以当我们自动赋值时,便是基本数据类型转换为包装器类型,也就是自动装箱。便是调用Integer的valueOf(int)方法。
jdk源码为:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
其中 IntegerCache方法
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() {}
}
从这段代码可以看出
1.IntegerCache.cache中存在一些对象的引用,在Java中一般为-128~127,我们称其为缓冲范围。而不在缓冲范围中的
则会new 一个新的对象。
2.IntegerCache中规定了缓冲范围下限为-128,但上限没规定,可以通过更改IntegerCache.high值更改上限大小,IntegerCache.high小于127,则上限还是127,大于127上限则为更改值。更改方法为在VM args中更改Djava.lang.Integer.IntegerCache.high。