在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处理==符号仍然是在比较地址。
本文探讨了Java中使用==与基础类型比较时的行为差异,解释了自动拆箱操作如何影响对象比较结果,并通过字节码分析进一步解析这一过程。
171万+

被折叠的 条评论
为什么被折叠?



