Java自动装箱的陷阱

今天看《深入理解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)

你可能感兴趣的:(Java自动装箱的陷阱)