基本数据类型:因为基本数据类型没有引用对象,所以 “==” 的效果就是比较值是否相同,基本数据类型没有 equals 方法
引用数据类型:“==” 和 equals 两者都是比较引用的对象是否相同
为什么我们在网上会看到说:双等比较引用,equals比较值呢?
那是因为equals被重写了,重写之后的效果就是比较值是否相等,那些例子都是用String类型之间进行比较的,String内部默认重写了equals方法,所以才有了以上的说法
如下是equals的源码,可以看到equals的内部实现就是 “==”
public boolean equals(Object obj) {
return (this == obj);
}
如下是String内部重写equals的源码
- String内部重写了equals方法,重写后的效果就是比较两个对象的值是否相等
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;
}
对应引用数据类型来说,可以这样记:
-
如果equals没有被重写,两种比较是相同的
-
如果equals被重写了,那么两种比较自然不同
-
String内部默认重写了equals方法,所以:”==“ 比较引用,equals 比较值
String测试
(”==“ 比较引用,equals 比较值)
直接定义两个值相同的字符串进行比较
String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2); // true
System.out.println(str1.equals(str2)); // true
在创建字符串的时候,会先创建一个字符串缓冲池
当创建str1时,先在字符串常量池中寻找有没有对应“hello”的对象,如果没有,就创建一个,然后将str1对象放入字符串常量池中,将str1的值“hello”放入常量池中
JDK1.7后:字符串常量池保存引用,常量池保存值
当创建str2时,先在字符串常量池中寻找有没有对应“hello”的对象,发现str1对应的值和自己要创建的字符串值相同,就直接引用str1所引用的对象
所以
- str1==str2:两者引用的对象相同,都是“hello”;
- str1.equals(str2)也相同:两者的值相同
直接定义两个值不同的字符串进行比较
String str1 = "hello";
String str2 = "hi";
System.out.println(str1 == str2); // false
System.out.println(str1.equals(str2)); // false
- 两者所引用的对象不同,所以 str1 == str2 肯定为false
- 两者的值也不同,所以下面的也是false
new两个值相同的字符串进行比较
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2); // false
System.out.println(str1.equals(str2)); // true
在new一个对象的时候,不会从字符串缓冲池中寻找,而是直接开辟一个新的空间来创建一个新的对象,创建的对象也不会添加到常量池中
所以
- new了两个对象,两个对象的引用肯定不是同一个,双等的比较为false
- 但是两个对象的值是相同的,都是“Hello”,所以equals的比较相同为 true
new两个值不同的字符串进行比较
String str1 = new String("Hello");
String str2 = new String("Hi");
System.out.println(str1 == str2); // false
System.out.println(str1.equals(str2)); // false
- new了两个对象,两个对象的引用肯定不是同一个,双等的比较为false
- 两个对象的值也是不相同的,所以equals的比较不同为 false
直接定义一个字符串和new一个字符串进行比较(两者值相同)
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
直接定义一个字符串和new一个字符串进行比较(两者值不同)
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
其它对象测试
(”==“ 比较引用,equals 也比引用)
首先创建一个实体类
class Person {
private int id;
public Person(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
new 两个值相同的对象
Person person1 = new Person(12);
Person person2 = new Person(12);
System.out.println(person1 == person2); // false
System.out.println(person1.equals(person2)); // false
- 因为equals没有被重写,所以两种比较都是一样的,都为false
new两个值不同的对象
Person person1 = new Person(12);
Person person2 = new Person(25);
System.out.println(person1 == person2); // false
System.out.println(person1.equals(person2)); // false
- 因为equals没有被重写,所以两种比较都是比较引用是否相同,和对象的值无关,所以都为false
总结
基本数据类型:因为基本数据类型没有引用对象,所以 “==” 的效果就是比较值是否相同,基本数据类型没有 equals 方法
引用数据类型:“==” 和 equals 两者都是比较引用的对象是否相同
- equals 方法可以被重写
- String内部默认重写了 equals 方法,使其效果为判断两者的值是否相等
- 创建字符串时,会先在字符串常量池中进行查找