Java面试系列文章
Java equals 和 ==的区别
1. “==” 运算符
对于基本类型和引用类型 ==
的作用效果是不同的,如下所示:
如果作用于基本数据类型的变量,则直接比较其存储的 值是否相等。
如果作用于引用类型的变量,则比较的是所指向的对象的地址是否相等。
其实==
比较的不管是基本数据类型,还是引用数据类型的变量,比较的都是值,只是引用类型变量存的值是对象的地址。
代码示例:
int x = 10;
int y = 10;
String str1 = new String("abc");
String str2 = new String("abc");
String str3 = "abc";
String str4 = "abc";
System.out.println(x == y);
System.out.println(str1 == str2);
System.out.println(str1.equals(str2));
System.out.println(str3 == str4);
执行的结果:
true
false
true
true
代码解读:因为 x 和 y 指向的是同一个引用,所以 ==
也是 true
,而 new String()
方法则重写开辟了内存空间,所以 ==
结果为 false
,而 equals
比较的一直是值,所以结果都为 true
。
2. “equals()” 方法
首先,equals()
方法不能作用于基本数据类型的变量,
另外,equals()
方法存在于Object
类中,而Object
类是所有类的直接或间接父类,所以说所有类中的equals()
方法都继承自Object
类,在没有重写equals()
方法的类中,调用equals()
方法其实和使用==
的效果一样,也是比较的是引用类型的变量所指向的对象的地址,不过,Java
提供的类中,有些类都重写了equals()
方法,重写后的equals()
方法一般都是比较两个对象的值,比如String
类。
Object
类equals()
方法源码:
public boolean equals(Object obj) {
return (this == obj);
}
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
本质上就是 ==
,只不过 String
和 Integer
等重写了 equals
方法,把它变成了值比较。看下面的代码就明白了。
首先来看默认情况下 equals
比较一个有相同值的对象,代码如下:
package com.tinghs.springbootaction;
public class Student {
private int age;
public Student(int age) {
this.age = age;
}
}
Student student1 = new Student(23);
Student student2 = new Student(23);
System.out.println(student1.equals(student2));
执行的结果:
false
此时equals
方法调用的是基类Object
类的equals()
方法,也就是==
比较。
equals
源码如下:
publicbooleanequals(Object obj){
return (this == obj);
}
原来 equals
本质上就是 ==
,所以返回false
。
然后我们重写下equals()
方法,只要两个学生的年龄相同,就认为是同一个学生。
package com.tinghs.springbootaction;
public class Student {
private int age;
public Student(int age) {
this.age = age;
}
@Override
public boolean equals(Object obj) {
Student student = (Student) obj;
return this.age == student.age;
}
}
Student student1 = new Student(23);
Student student2 = new Student(23);
System.out.println(student1.equals(student2));
执行的结果:
true
此时再比较刚刚的两个实例,返回true。
3. 结论
==
对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals
默认情况下是引用比较,只是很多类重新了 equals
方法,比如 String
、Integer
等把它变成了值比较,所以一般情况下 equals
比较的是值是否相等。
- 两个对象的
hashCode()
相同,则equals()
也一定为true
,对吗?
不对,两个对象的hashCode()
相同,equals()
不一定true
。
代码示例:
String str1 = "通话";
String str2 = "重地";
System. out. println(String. format("str1:%d | str2:%d", str1. hashCode(),str2. hashCode()));
System. out. println(str1. equals(str2));
执行的结果:
str1:1179395 | str2:1179395
false
代码解读:很显然“通话”和“重地”的 hashCode()
相同,然而 equals()
则为 false
,因为在散列表中,hashCode()
相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等。