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 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() {}}
可以看到这个类中的low值为-128,high的值为127,但我们每次使用这个类时,都会执行类中静态代码块,也就是static中的一堆代码。那么这些代码的作用是什么呢?
该静态代码块主要用于初始化一个缓存数组,其中缓存了范围在 -128 到 127 之间的整数对象,以提高性能和节省内存。
因此在valueOf方法中当传递来的参数在-128到127之间时就会直接引用缓存数组中的整数值,不在这个范围则会创建新的对象,所以就造成128陷阱,因为在这个范围内数引用的都是同一个对象,所以=会判定其相等,超出这个范围创建新的对象表示,=当然就不会判定这两个新对象相等。