一、128陷阱演示
public static void main(String[] args) {Integer a = 110;Integer b = 110;Integer c = 130;Integer d = 130;System.out.println(a==b);System.out.println(c==d);}
在上面的方法中我定义了四个变量a、b、c和d并且进行了两次比较。你认为输出结果是什么?难道是true和true吗?请看下面的测试结果。
二、结果分析及讲解
答案并不是我们认为的两个true 而是一个true和一个false,这是我们就会想了,为什么都是Integer的比较,上边的是true,下边的就是false了?
到了这一步就要分析分析源码了,在我们进行声明的时候例如声明Integer a = 110,在我们的代码被编译之后,这行代码就等同于下图所示的代码。
Integer a = 110;//Integer a = Integer.valueOf(110)Integer b = 110;//Integer b = Integer.valueOf(110)Integer c = 130;//Integer c = Integer.valueOf(130)Integer d = 130;//Integer d = Integer.valueOf(130)
其中注释的部分就是编译后对代码做出的调整。好的,既然我们要比较的是a和b,我们代码跟进到Integer类当中去查看这个方法。
public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}
Integer类中的valueOf方法需要一个参数,就是我们为Integer对象赋的值,然后进行if判断,那么判断的又是什么呢?实际上有着这么一个缓存类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 propertyint 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_VALUEh = 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() {}}
这个IntegerCache类当中有着这么几个变量,low,high和cache[],low和high代表着这个缓存数组catch可以存储的数的范围,具体的代码不在讲解,通过static静态块将catch数组初始化,如果没有额外的配置,那么这个数组存储的数的范围就是-128~127之间。
现在回到我们的valueOf方法当中,知道了IntegerCache是什么之后,下边的部分就很好理解了,如果我们的参数范围在IntegerCache类的缓存数组的存储范围之内,我们就直接将存储在cache数组中的这个Integer返回,否则的话我们就会new出一个新的Integer来保存我们的值。
public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}
回到我们最开始的部分。
public static void main(String[] args) {Integer a = 110;Integer b = 110;Integer c = 130;Integer d = 130;System.out.println(a==b);System.out.println(c==d);}
现在你是否可以明白a==b为什么为true以及c==d为什么为false了吗?就是因为a与b拿到的都是缓存数组当中的一个值,而c和d拿到的都是new出的新的Integer,他们的地址是不同的,所以是false,既然Integer是一个包装类,比较包装类中的一些属性我们能够想到一个方法equals,那么equals方法是否可行呢?答案是可以的。
本次文章就到这里了,对大家有帮助的话还希望大家给博主一个关注。