在Java中要对两个对象进行比较,用==是不行的,因为==默认比较两个对象在内存中的地址,而不是对象的内容。但是像下面这两种情况:
1:
Integer a = new Integer(2);
Integer b = new Integer(3);
boolean res = (a > b || a == b || a < b);
2:
Integer a = new Integer(10);
Integer b = new Integer(10);
boolean res = (a > b || a == b || a < b);
由于对基础知识点的理解不扎实,我一开始就认为这两种情况中得到的res值都为true,为什么?如果是做值的比较,那么大于,等于或小于总该有一种满足吧(我想当然的就这样认为了),如果是做地址的比较,那么三者也是必取其一。
但是,事实在我写好两段程序,编译运行之后发现,绝非我想的如此:
第一种情况中res的值为true,第二种情况res的值却为false,而两者唯一的不同之处仅在给出的初始值不同,但这正好说明两段程序中不是单纯地进行了值或者地址的比较。
后来查了点资料才了解到,Java中有一种自动拆箱的操作,对于基本类型的封装类,>和<符号,满足该操作;而==符号进行的仍然是地址的比较,这样就能解释上面的现象了。
a > b或a < b对于初始值不同的两个类,必有一个为true,最后结果即为true,而对于初始值相同的两个类,则为false, ==进行的地址比较也为false,才得到了第二种情况最终的结果。
可以从字节码中很清楚的看出这其中的不同,编译之后,用javap -verbose XXX(类名)查看字节码:
public static void main(java.lang.String[]);
Code:
Stack=3, Locals=4, Args_size=1
0: new #2; //class java/lang/Integer
3: dup
4: bipush 10
6: invokespecial #3; //Method java/lang/Integer."<init>":(I)V
9: astore_1
10: new #2; //class java/lang/Integer
13: dup
14: bipush 10
16: invokespecial #3; //Method java/lang/Integer."<init>":(I)V
19: astore_2
20: aload_1
21: invokevirtual #4; //Method java/lang/Integer.intValue:()I
24: aload_2
25: invokevirtual #4; //Method java/lang/Integer.intValue:()I
28: if_icmpgt 47
31: aload_1
32: aload_2
33: if_acmpeq 47
36: aload_1
37: invokevirtual #4; //Method java/lang/Integer.intValue:()I
40: aload_2
41: invokevirtual #4; //Method java/lang/Integer.intValue:()I
44: if_icmpge 51
47: iconst_1
48: goto 52
51: iconst_0
52: istore_3
53: return
//Method java/lang/Integer.intValue:()
21,25,27,41行说明,jvm在进行数值对象比较时,调用Integer.intValue(),把类类型转换成为了基本数据类型,就是比较具体的数值,不再是类地址了,而31,32行说明,jvm处理==符号仍然是在比较地址。