Integer的比较
之前做了牛客的一道选择题,发现了这个,在这里总结总结,上题:
- 在jdk1.5之后,下列 java 程序输出结果为______。
1. int i = 0;
2. Integer j = new Integer(0);
3. System.out.println(i == j);
4. System.out.println(j.equals(i));
分析如下(下面的分析只讨论自动拆装箱的情况,不考虑new新对象的情况):
- 基本型和基本型封装型进行
==
运算符的比较,基本型封装型将会自动拆箱变为基本型后再进行比较 - 两个Integer类型进行
==
比较,如果其值在-128
至127
,那么返回true
,否则返回false
, 这跟Integer.valueOf()
的缓冲对象有关,下面详讲。(注意:这里只看自动拆装箱的情况) - 两个基本型的封装型进行
equals()
比较,首先equals()
会比较类型,如果类型相同,则继续比较值,如果值也相同,返回true
,和正常的对象调用equals()
方法对比一模一样 - 基本型封装类型调用
equals()
,但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型,再进行上述两个基本型的封装型的比较
因此,上述题目的答案为,
true
,true
,第三行是因为,j会自动拆箱,相当于0 == 0
,因此就是true
,第四行是因为,i会自动装箱,相当于j.equals(0的自动装箱类)
,因此也是true
。
Integer.valueOf()缓冲对象
- 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);
}
我们可以看到,如果i
在某一个范围之内的时候,会从if
中返回对象的引用,这也就是本次问题的根源所在,那么我们从这里下手继续探究,来看一看IntegerCache
干了什么。
IntegerCache
是一个静态内部类,我们可以看到一个静态代码块,如果我们用到了自动装箱,就会调用valueOf()
,也就是说会触发IntegerCache
的类加载,也就是说,会完成静态代码块的加载,在其内部会完成-128~127
的Integer
数组的定义,即这里的Integer cache[]
,这下我们就明白了,为什么自动装箱的两个Integer对象进行==
比较的时候,如果范围在-128~127
的时候,会返回true
,因为他们都是指向同一对象的。
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() {}
}