我们先简单地了解一下它们的概念,简单地来说,equals比较的是两个对象之间的引用地址是否相同,而==是比较的两个对象之间的数值是否相等。
我们先看下面的代码
package gouzaos;
public class Str {
public static void main(String[] args) {
String str1 = "子月";
String str2 = "子月";
String str3 = new String("子月");
String str4 = new String("子月");
System.out.println(str2.equals(str3));
}
}
这里我们就直接分析结果
str1==str2 str1.equals(str3) str3!=str4
这里子月画了一幅图
从图里可以看出,在JVM中,str1 str2 直接就是初始化到字符串常量池的,所以它们是相等的,str3 new 了一个String ,对应的直接就在堆里面new出了一个和str1 相同的0x87地址,然后又指向了常量池里面的0x87, str1的引用地址是0x87,strt3的引用地址也是0x87 所以用equals判断的时候它们是相等的。 要是子月来理解str3和str4来说,它们都new了,必然不同,但是equals的时候就是对的。(因为重写了父类的equels方法,这里把String 变成StringBuffer的时候,就会报错,因为StringBuffer是可变的字符串,没有重写父类的equels方法。)
//对的
new String("子月").equals(new String("子月"));
//错的
new StringBuffer("子月").equals(new StringBuffer("子月"));
这里子月再拓展一个问题,下面的一段代码到底创建了几个String Object呢?
//String str ="子月";
String str 1= new String("子月");
这已经是一个新的问题了哦
我们先说答案,————一个或者两个。
这个时候大家就会疑惑了,不是new了一次吗?怎么会是两个呢?
其实很简单,大家联系着上一张子月画的图来理解,假如没有问题中所注释的那段代码,那么str的创建是怎么来的呢? 首先new 了一个堆中的地址,然后再指向数据共享区中的字符串常量池,检查其中是否存在着“子月”,假如没有,那么就再new一个关于“子月”的地址,这样就是两个。
那什么时候是一个呢? 那就是当注释的那段代码存在时,字符串常量池中就已经存在一个"子月"的地址了,就不用再次new了,也就变成一次了。
这里子月又想到了一个问题,来考考大家,看代码说结果。
package gouzaos;
public class Str {
public static void main(String[] args) {
StringBuffer str1 =new StringBuffer("子月");
StringBuffer str2 = str1.append("abc");
System.out.println(str1==str2);
}
}
答案是 true 那为什么是ture呢?因为str2并没有返回一个新的对象,只是在str1上进行的追加,还是本身的地址。所以是true。
突然又想到了一个问题,请看一下代码
package gouzaos;
public class Str {
public static void main(String[] args) {
String str ="aa.bb.cc";
str.substring(2,6);
//String a= str.substring(2,6);
//System.out.println(a);
System.out.println(str);
}
}
是不是你的答案为.bb. 呢?子月悄悄地告诉你,错了哦。正确的答案为aa.bb.cc
那为什么是aa.bb.cc呢?因为当使用substring截取字符串后会产生一个新的字符串,你必须为操作后的字符串定义一下,才能输出真正地截取后的字符串。



