目录
4.3直接定义一个字符串和new一个字符串进行比较(两者值相同)
4.4直接定义一个字符串和new一个字符串进行比较(两者值不同)
|---------------------|
| 🎈边走、边悟🎈迟早会好 |
== 和 equals 有什么区别?这个问题本身不难,但是被问到的频率很高,且大部分人的回答都不够全面,让人听了有种"恨铁不成钢"的感觉,所以今天咱们就来好好聊聊这个问题。
一、Object对象
对于 Object 来说,其 equals 方法底层实现就是"==",如下 JDK 的 Object 源码如下:
java
public boolean equals(Object obj) {
return (this == obj);
}
也就是说,对于 Object 对象来说,equals 和 == 都是一样的,都是比较对象的引用是否相同。
二、==
- 基本数据类型(也称原始数据类型) :byte,short,char,int,long,float,double,boolean。他们之间的比较,应用双等号(==),比较的是他们的值。
- 引用数据类型:当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址(确切的说,是堆内存地址)。
注:对于引用数据类型种类型,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。因为每new一次,都会重新开辟堆内存空间。
三、String类的equals()方法
现在我们拿String类来举例:我们去\src\java\lang目录中找到String类,发现equals方法被重写如下:
java
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
上述代码可以看出,String类中被重写的equals()方法其实是比较两个字符串的值是否相等。
-
如果equals没有被重写,两种比较是相同的
-
如果equals被重写了,那么两种比较自然不同
-
String内部默认重写了equals方法,所以:"==" 比较引用,equals 比较值
下面我们通过实际代码来看看String类的比较。
四、示例
("==" 比较引用,equals 比较值)
4.1直接定义两个相同的值比较
java
String str1 = "tingyi";
String str2 = "tingyi";
System.out.println(str1 == str2); // true
System.out.println(str1.equals(str2)); // true
JDK1.7后:字符串常量池保存引用,常量池保存值
在创建字符串的时候,会先创建一个字符串缓冲池,当创建str1时,先在字符串常量池中寻找有没有对应"hello"的对象,如果没有,就创建一个,然后将str1对象放入字符串常量池中,将str1的值"hello"放入常量池中。
当创建str2时,先在字符串常量池中找有没有对应"hello"的对象,发现str1对应的值和自己要创建的字符串值相同,就直接引用str1所引用的对象
- 两者引用的对象相同,都是"hello",所以==为true
- 两者的值也相同,所以equals为true
4.2直接定义两个值不同的字符串进行比较
java
String str1 = "tingyi";
String str2 = "ting";
System.out.println(str1 == str2); // false
System.out.println(str1.equals(str2)); // false
- 两者所引用的对象不同(引用的地址也就不一样),所以 str1 == str2 肯定为false
- 两者的值也不同,所以下面的也是false
4.3直接定义一个字符串和new一个字符串进行比较(两者值相同)
java
String str1 = "Hello";
String str2 = new String("Hello");
System.out.println(str1 == str2); // false
System.out.println(str1.equals(str2)); // true
- 因为str2 new了一个新对象,所以和str1的引用不是同一个,所以==的比较为false
- 但是两者的值是相同的,所以equals的比较为 true
4.4直接定义一个字符串和new一个字符串进行比较(两者值不同)
java
String str1 = "Hello";
String str2 = new String("Hi");
System.out.println(str1 == str2); // false
System.out.println(str1.equals(str2)); // false
- 因为str2 new了一个新对象,所以和str1的引用不是同一个,==的比较为false
- 两者的值是不相同的,所以equals的比较也为 false
五、小扩展
public class ObjectDemo{
public static void main(String[] args) {
String s1 = "Hello";
String s2 = new String("Hello");
s2 = s2.intern();
System.out.println(s1 == s2); // true
System.out.println(s1.equals(s2)); // true
}
}
上述代码的第5行中,java.lang.String的intern()方法"Hello".intern()方法的返回值还是字符串"Hello",表面上看起来好像这个方法没什么用处。
但实际上,它做了个小动作:检查字符串池里是否存在"abc"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会 把"Hello"添加到字符串池中,然后再返回它的引用。
六、总结:
为了分析上面的代码,我们必须首先分析堆内存空间和栈内存空间,这一点非常重要:
- ==:比较的是两个字符串内存地址(堆内存)的数值是否相等,属于数值比较;
- equals():比较的是两个字符串的内容,属于内容比较。
🌟感谢支持 听忆.-CSDN博客
|--------------------|
| 🎈众口难调🎈从心就好 |