- Integer的.equals和==
- 思考最初的问题
- 初始化缓存的过程如下
Integer的.equals和==
这是一个基础的问题,掌握一些java的人,或许能讲出一些为什么。但是再深究一下才会发现这究竟是为什么
一段普通的代码
public class Demo {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
System.out.println(i1 == i2); //输出true
i1 = 1000;
i2 = 1000;
System.out.println(i1 == i2); //输出false
}
}
JDK1.5之后,编译器提供了自动拆箱和装箱的功能,Integer i = 100 正是编译器帮我们自动装箱了。
看下反编译的代码
public class Demo {
public static void main (String [] args){
Integer i1 = Integer.valueOf(100);
Integer i2 = Integer.valueOf(100);
System.out.println(i1==i2);
i1 = Integer.valueOf(1000);
i2 = Integer.valueOf(1000);
System.out.println(i1==i2);
}
}
这就是自动装箱的过程。接下来我们再看下在valueOf有发生了什么,直接粘贴源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
再来看看方法中的逻辑,这个方法会判断传入的int值是否在IntegerCache 的最高值和最低值之间,如果在这个之间,就会从IntegerCache 的缓存中获取Integer对象,否则就会new一个新的Integer对象。
在这之前还有个静态代码块
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;
}
从这里可以看出Integer在-128 到127之间做了一个数组
IntegerCache.cache 中的元素是-128到127顺序排列在数组的0-256位置,假设我们传入的i = -128,通过寻址公式计算下标
i + (-IntegerCache.low) = -128 + (128) = 0
到了这一步我们就可以明白了:为什么当Integer的值为 [-128, 127] 时,用== 判断两个两个值相等的Integer可以得到true,而超出这个范围后,用 == 判断两个两个值相等的Integer却得到false?因为当值在[-128, 127] 之间时,valueOf 方法不会创建新的Integer对象,而是从缓存中获取,这样一来,值相同的int,计算所得的下标是一样的,自然会获取到同一个Integer对象。而超出这个范围就不会从缓存中获取了,每次都new一个新的Integer对象,两个不同的对象的内存地址不同,用==自然会得到false。
初始化缓存的过程如下获取JVM的中的参数java.lang.Integer.IntegerCache.high,将其转为int类型,作为high的值
计算high 与low 之间的差值并+1作为缓存数组的长度
从-128开始连续递增,给缓存数组的每个位置设置Integer对象。



