今天看《深入理解Java虚拟机》,其中作者留了一段代码,让读者自己试试,运行结果和我预想的完全不一致,因此记录下来,做个总结。
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
System.out.println("c == d :"+(c == d));
System.out.println("e == f :"+(e == f));
System.out.println("c == (a + b) :"+(c == (a + b)));
System.out.println("c.equals(a + b) :"+c.equals(a + b));
System.out.println("g == (a + b) :"+(g == (a + b)));
System.out.println("g.equals(a + b) :"+g.equals(a + b));
以上代码输出结果如下:
c == d :true
e == f :false
c == (a + b) :true
c.equals(a + b) :true
g == (a + b) :true
g.equals(a + b) :false
这里有两个疑惑:
为什么 c == d
但是 e != f
?
这其中有两个原因,一是Integer赋值过程自动装箱;二是-128~127
范围内的Integer的cache。
- 自动装箱
Integer c = 3
编译后结果如下:
Integer c = Integer.valueOf(3);
-
-128~127
范围内的Integer的cache
在-128~127
范围内的数据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);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
}
基于以上两条,才会出现c == d
但是 e != f
这种情况
为什么 g == (a + b)
但是g.equals(a + b) == false
?
这是因为,编译期间遇到算术运算符会自动拆箱(⚠️==
运算在不遇到算术运算符的情况下不会自动拆箱):
System.out.println("g == (a + b) :"+(g == (a + b)));
编译结果如下:
System.out.println("g == (a + b) :"+(g.intValue() == (a.intValue() + b.intValue()));
因此,才会出现g == (a + b)
至于g.equals(a + b) == false
,完全是由于对象类型不一致(Long和Integer)