128陷阱介绍及演示
首先什么是128陷阱?
Integer包装类两个值大小在-128到127之间时可以判断两个数相等,因为两个会公用同一个对象,返回true,
但是超过这个范围两个数就会不等,因为会变成两个对象,返回false。
举个例子:
现有以下程序
public static void main(String[] args) {
Integer a = 125;
Integer b = 125;
Integer c = 129;
Integer d = 129;
System.out.println(a==b);
System.out.println(c==d);
}
结果输出如下:
前两个在范围内的变量在判断相等为真,后两个在判断相等时为假。
源码分析
我们创建变量时使用的代码
Integer a = 125;
在编译后其实会转变为
Integer a = Integer.valueOf(125);
因此我们在设置变量时执行的其实是Interger类的valueOf方法。
那么我们在源码中查看该方法
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() {}
}
可以看到这个类中的low值为-128,high的值为127,但我们每次使用这个类时,都会执行类中静态代码块,也就是static中的一堆代码。那么这些代码的作用是什么呢?
该静态代码块主要用于初始化一个缓存数组,其中缓存了范围在 -128 到 127 之间的整数对象,以提高性能和节省内存。
因此在valueOf方法中当传递来的参数在-128到127之间时就会直接引用缓存数组中的整数值,不在这个范围则会创建新的对象,所以就造成128陷阱,因为在这个范围内数引用的都是同一个对象,所以=会判定其相等,超出这个范围创建新的对象表示,=当然就不会判定这两个新对象相等。