1.问题引入
分别引入了int和Integer变量,并进行比较
int b = 128;
int b1 = 128;
Integer d = 127;
Integer d1 = 127;
Integer e = 128;
Integer e1 = 128;
System.out.println(b==b1);
System.out.println(d==d1);
System.out.println(e==e1);
System.out.println(e.equals(e1));
其输出结果如下
我们可以看到以下三个问题
(1)当数据为int类型的时候,运行的结果为true,
(2)如果是封装类型Integer的时候,数据为127的时候结果为true,但是到了128及以上就变成了false(128陷阱)
(3)使用equals时,同样的数据运行结果却为true
为什么会这样呢?
2.==和equals
基本类型的数据的变量名和值都存在栈中(作为类的属性的情况除外
==:
对于基本数据类型,比较的是栈中数据是否相同,只要数据没有改变,其运行都会为true;
对于引用数据类型,则比较的是所指向对象的地址值是否相等
equals:
如果没有对 equals 方法进行重写,则相当于“==”,比较的是引用类型的变
量所指向的对象的地址值;重写了,比较的是对象的值。
通过如上解释就可以说明(1)、(3)问题了。
3.128陷阱原因
(1)什么是128陷阱
Integer 数据类型使用“==”比较时,如果对象值的范围超出-128--127,那么两个对象值相同的情况下,返回的结果是false。
(2)寻找原因
当Integer a = xxx时,其底层会自动转换成为Integer a = Integer.valueOf(xxx)
所以让我们一起看看 Integer的 valueOf 方法的源码:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
通过以上代码,我们可以看到valueOf存在范围,在范围内会返回cache数组,超过了就会重新new一个新的内存空间
原因总结:Integer的ValueOf0方法当中,如果数值在最小值和最大值(-128~127)之间的数据都存储在一个cache数组中,该数组相当于一个缓存,当我们在该范围之间进行自动装箱的时候,程序就直接返回该值在数组中的内存地址(cache数组的地址),所以在-128~127之间的数值用==进行比较是相等,而不在这个区间的数,需要新开辟—个内存空间,所以不相等。
(3)陷阱范围
通过查看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) {
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() {}
}