关于equals和==的困惑
值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。
Java中的==
1.== 操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
2.==比较的是2个对象的地址,而equals比较的是2个对象的内容。
Java中的equals
1.equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。
总结
当equals为true时,==不一定为true
String类型中的 equals 和 ==
先来一段代码:
String s1 = "ARCHer"; String s2 = new String("ARCHer"); String s3 = "ARCHer"; String s4 = new String("ARCHer"); String s5 = "Hello ARCHer"; if(s1 == s2) System.out.println("s1 == s2"); else System.out.println("s1 != s2"); if(s1.equals((s2))) System.out.println("s1 equals s2"); else System.out.println("s1 not equals s2"); if(s1 == s3) System.out.println("s1 == s3"); else System.out.println("s1 != s3"); if(s1.equals((s3))) System.out.println("s1 equals s3"); else System.out.println("s1 not equals s3"); if(s2 == s4) System.out.println("s2 == s4"); else System.out.println("s2 != s4"); if(s2.equals((s4))) System.out.println("s2 equals s4"); else System.out.println("s2 not equals s4"); if(s1 == s5) System.out.println("s1 == s5"); else System.out.println("s1 != s5"); if(s1.equals((s5))) System.out.println("s1 equals s5"); else System.out.println("s1 not equals s5");
展示一下结果:
s1 != s2 s1 equals s2 s1 == s3 s1 equals s3 s2 != s4 s2 equals s4 s1 != s5 s1 not equals s5
程序在运行的时候会创建一个字符串缓冲池当使用。也就是说,我定义的s1 = "ARCHer"后,这段字符串被写入缓冲池,当定义s3的时候,会在缓冲池中寻找,找到了一段相同的字符串,因此s1 == s3。
而在定义s2的时候,我使用了new,也就是新开辟一块空间,来装这段字符串,所以==的时候s1 != s3。而equals比较聪明,它不会去管三七二十一,我就是比较两个的值是不是相同,发现ARCHer和ARCHer相同,因此,s1 equals s3。
可以这样理解:== 比较的是两个变量的地址,而equals是比较两个变量的值。(C语言中讲到,函数是求值运算,也就是先将传入的参数表达式求值后再进行运算,我想应该和这里是异曲同工之妙。而==并不是函数,应该叫做运算符,比较两个变量的地址。)
还不尽兴,再做个小小的补充,在上面的基础上,加一段代码:
String s6 = new String("ARCHer").intern();
if(s1 == s6) System.out.println("s1 == s6"); else System.out.println("s1 != s6"); if(s1.equals((s6))) System.out.println("s1 equals s6"); else System.out.println("s1 not equals s6");
猜猜结果?没错是:
s1 == s6 s1 equals s6.intern()的返回值还是原来的字符串,但是,背后还做了一个小动作,相信大家都看出来了——检查字符串池里是否存在"ARCHer"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会把"ARCHer"添加到字符串池中,然后再返回它的引用。