包装类的陷阱

2021-05-10  本文已影响0人  lenny611

基于JDK1.8,先上代码:

public class Wrapper {
    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);
        System.out.println(e==f);
        System.out.println("——————————");
        System.out.println(c==(a+b));
        System.out.println(c.equals(a+b));
        System.out.println("——————————");
        System.out.println(g==(a+b));
        System.out.println(g.equals(a+b));
    }
}

大家可以先猜猜答案。
答案如下:


结果.png

现在开始答主自己的解释环节:
c==d和e==f结果不同涉及到一个缓冲池的概念,就是包装类Integer会将-127~127之间的数据存在缓冲池中,超过了这个范围则在堆中重新分配一块区域,==比较的是地址,所以c==d为true,而e和f的值超出了缓冲池值的范围,所以地址必然不同,所以为false

c==(a+b)和c.equals(a+b),先介绍一个知识点,包装类只有在不遇到算术运算符的情况下不会自动拆箱,而c==(a+b)明显已经涉及了+算术运算符,所以这里做了自动拆箱,所以==在这里比较的是值,所以c==(a+b)的结果为true,而c.equals(a+b),先来看看JDK1.8下包装类Integer的equals实现:


equals实现.png

如图所示,equals方法,首先先做了类型检查,进而再去比较值,所以(a+b)结果为integer类型,所以通过了类型检查,且值相等,所以返回true。包装类Long的equals实现是类似的,在这里就不展示了,所以g==(a+b)在这里也碰到了算术运算,所以g==(a+b)这里的==比较的是值,所以结果为true,而g.equals(a+b)是先做了类型检查,(a+b)类型为integer,所以直接返回false。

然后再来说说答主为什么遇到这个坑:
深入了解Java虚拟机(第二版,周志明,蓝色封面)这本书中一样的例子,但是解释是如下这样


image.png

因为这本书是基于JDK1.7的,而答主的环境是JDK1.8,所以结果跟看到的不同,而且包装类在JDK1.8中是做了类型检查的,与书中不符,原因很可能是JDK1.7和1.8不同,有兴趣的可以自己在JDK1.7下试试看。

上一篇下一篇

猜你喜欢

热点阅读