在分析128陷阱之前首先需要了解几个前置概念
包装器类型
由于在使用集合类(Set、Map、List)时需要有对象传入,而Java语言的8种基本数据类型(int、short、long、float、double、boolean、byte、char)放不进去,因此需要包装器类型对基本数据类型进行包装
自动拆箱
自动拆箱(Unboxing):将包装类对象转换为对应的基本数据类型。
自动拆箱通过xxxValue()实现,(xxx为基本数据类型)例子如下:
Integer a=10;
Integer b=a.intValue();
System.out.println(a==b);
打印结果:true
自动装箱
自动装箱(Autoboxing):将基本数据类型转换为对应的包装类对象。
自动拆箱通过.valueOf()实现,例子如下:
Integer c=10;
Integer d=Integer.valueOf (10);
System.out.println(c==d);
打印结果:true
了解以上概念之后我们来了解128陷阱
128陷阱实例:
Integer num1 = -128;
Integer num2 = -128;
System.out.println(num1 == num2);
打印结果:true
Integer num1 = 127;
Integer num2 = 127;
System.out.println(num1 == num2);
打印结果:true
Integer num3 = 128;
Integer num4 = 128;
System.out.println(num3 == num4);
打印结果:false
上述代码可以看出,当num取值位于-128-127时,打印的结果均为true,这说明num1、2对应地址一致,num3、4对应地址一致,而超出127之后,出现了地址不一致问题,接下来我们查看一下Integer包装类型的源码:
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) -1);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
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);
}
结论:128陷阱产生原因
Integer类在加载的时候会加载内部的静态类IntegerCache,该类在加载中会从-128-127构建一个Integer数组存起来,当我们使用自动装箱时会直接从数组中取对象使用,Integer a=10 和 Integer b=10指向的对象就是相同的对象此时返回true,当valueOf()超过该范围(-128-127)后,就会new Integer创建新的对象,此时a==b返回false