Java语法糖中自动装箱的陷阱

一、程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Main {
public static void main(String[] args) {
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); // true
System.out.println(e == f); // false
System.out.println(c == (a + b)); // true
System.out.println(c.equals(a + b)); // true
System.out.println(g == (a + b)); // true
System.out.println(g.equals(a + b)); // false
}
}

二、问题

1、为什么c == d但是e != f?

解答:这其中有两个原因,一是Integer赋值过程自动装箱;二是-128~127范围内的Integer的cache。

  • 自动装箱
1
Integer c = 3;

编译后结果如下

1
Integer c = Integer.valueOf(3);
  • -128~127范围内的Integer的cache

-128~127范围内的数据Integer.valueOf()返回的是同一个对象;

1
2
3
4
5
6
7
8
9
10
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这种情况。

除此之外,LongShort也具有这样的性质!!!

2、为什么 g == (a + b) 但是g.equals(a + b) == false

这是因为,编译期间遇到算术运算符会自动拆箱(⚠️==运算在不遇到算术运算符的情况下不会自动拆箱):

1
System.out.println("g == (a + b) :"+(g == (a + b)));

编译结果如下:

1
System.out.println("g == (a + b) :"+(g.intValue() == (a.intValue() + b.intValue()));

因此,才会出现g == (a + b)

至于g.equals(a + b) == false,完全是由于对象类型不一致(Long和Integer)。