观察以下代码运行结果
Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e = 321; Integer f = 321; Long g = 3L; Long h = 2L; 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 System.out.println(g.equals(a+h));//true
将以上代码进行反编译得到
分析:
第一个和第二个看下Integer的源码,里面有个本地缓存的使用,对于-128到127之间到数值会使用缓存里面的对象,
也就是说 Integer c = 3 或者 Integer c = Integer.valueOf(3) ,最终 c 得到的是Integer里的缓存对象
同理,d也是获得该相同对象因此 进行 c == d 比较时,c和d引用的是同一个对象,因此就true
而对于321,已经超出缓存范围了,因此 valueOf 方法会生成一个新的Integer对象因此e和f就引用不同 的对象了,进行==比较,当然就false了
第三个由于a+b包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),==比较符又将左边的自动拆箱,因此它们比较的是数值是否相等。
第五个对于 g == (a+b),首先计算 a+b,也是先调用各自的intValue方法,得到数值之后,由于前面的g是Long类型的,也会自动拆箱为long,==运算符能将隐含的将小范围的数据类型转换为大范围的数据类型,也就是int会被转换成long类型,两个long类型的数值进行比较。
第六个对于 g.equals(a+b),同理a+b会先自动拆箱,然后将结果自动装箱,需要说明的是 equals 运算符不会进行类型转换。所以是Long.equals(Integer),结果当然是false
第七个对于g.equals(a+h),运算符+会进行类型转换,a+h各自拆箱之后是int+long,结果是long,然后long进行自动装箱为Long,两个Long进行equals判断。
牢记一句话:包装类在不遇到算数运算符的情况下不会触发自动拆箱,以及它们的equals()方法不处理数据类型的关系