在看深入理解java虚拟机时,作者在讲java语法糖的时候,举了例子比较java中==和equals的区别,代码如下
public class GenericTypes { public static void main(String[] args) { /** * 鉴于包装类的“==”运算在不遇到算术运算的情况下不会自动拆箱,以及它们equals()方法不处 理数据转型的关系 */ Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e = 321; //自动装箱为Integer Integer f = 321; //自动装箱为Integer Long g = 3L; //自动装箱为Long ListaIntegers = Arrays.asList(1,2,3,4); 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 }}
文中作者提到,包装类的“==”运算在不遇到算术运算的情况下不会自动拆箱。
对于为何 c==d 为true, 而e==f为false,原因是因为,在自动装箱时,因为原本Integer就已经缓存了-128~127的值,因此在自动装箱时,直接拿到常量池中缓存好的值的地址,因此 c== d, 而e和f为321 > 127 所以就等于新增对象,因此为false对于 c == (a + b) 为true ,反编译源码看到,
18: aload_3 19: invokevirtual #4 // Method java/lang/Integer.intValue:()I 22: aload_1 23: invokevirtual #4 // Method java/lang/Integer.intValue:()I 26: aload_2 27: invokevirtual #4 // Method java/lang/Integer.intValue:()I
,全部都拆箱为基本数据类型来比较,因此为true
对于c.equals(a + b) 为true,a + b 会自动拆箱变为基本类型, 但是在比较的时候又会自动装箱,equals比较值
对于g == (a + b)为true ,根据反编译源码看来 ,全部都拆箱为基本数据类型进行比较 ,因此为true
最后一个为何为false ,Long 和Integer 调用equals 为false