和群里大佬讨论了如下问题:
Integer a = 11;
Integer b = 11;
System.out.print(a==b?"相等":"不相等");
输出结果:相等
按照常理,Integer是包装类,属于是一个对象,对象之间用"=="比较是比较引用地址的,对于任意new出来的对象来讲,引用地址肯定不相同,那为何这里出现的是相等呢?
一步一步的分析:
Integer x = 11;
//等同于
Integer x = Integer.valueOf(11);
查看valueOf的源码实现:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
可知,形参i的值在 IntegerCache.low--Integer.high 之间时,会直接从缓存取数据然后返回,否则则new一个Integer对象回去。 我们知道非包装类的==是直接比较值的,new出来的对象肯定不相等的,所以这里11是在low和high之间,Integer是直接返回缓存中的数据。 查看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,根据上面的思路就知道了,在-128~127之间是直接返回int形非包装类,非包装类之间比较肯定用==啦。static表示初始化的时候仅会执行一次,这里面初始化了cache这个数组,我们的值就是从这个数组里取的,
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
可以看出cache里面存的-128-127,引用一个我感觉比较好的回答:
"这是Integer的静态内部类,在Integer类装入内存中时,会执行其内部类中静态代码块进行其初始化工作,做的主要工作就是把 [-128,127]之间的数包装成Integer类并把其对应的引用存入到cache数组中,这样在方法区中开辟空间存放这些静态Integer变量,同时静态cache数组也存放在这里,供线程享用,这也称静态缓存。我们知道在Java的对象是引用的,所以当用Integer 声明初始化变量时,会先判断所赋值的大小是否在-128到127之间,若在,则利用静态缓存中的空间并且返回对应cache数组中对应引用,存放到运行栈中,而不再重新开辟内存。"
可以测试一波:
Integer x1 = -128;
Integer y1 = -128;
System.out.println(x1==y1);
Integer x2 = -129;
Integer y2 = -129;
System.out.println(x2==y2);
Integer x3 = 127;
Integer y3 = 127;
System.out.println(x3==y3);
Integer x4 = 128;
Integer y4 = 128;
System.out.println(x4==y4);
结果是
true
false
true
false
这个题作为面试题,可以这样回答:Integer的值在-128-127之间时候,初始赋值会直接从Integer内部维护的一个静态缓存数组里去取,而不用重新开辟内存,所以在这个范围内的Integer实际上就是常量的比较,所以是相等的,其余的则是对象之间比较地址,所以不相等。