大家好我是 Ryanangry,今天来介绍一道常见面试题。面试场上经常遇到面试官问 == 和 equals 有什么区别,这时候有面试经验的小伙伴肯定已经熟烂于心,然而初次遇到这个问题的小伙伴们却多半会答的无厘头。下面我们一起通过源码分析一下这道面试题。
-
== 的含义
首先是基本数据类型, Java 中有八大基本数据类型,分别是 byte,short,int,long,float,double,boolean,char。== 在基本数据类型用使用的时候,直接比较的是变量存储的值是否相等。
其次是引用数据类型, 对于引用数据类型来说,使用 == 比较的是变量的内存地址是否相等。
-
equals 的含义
万物皆对象,首先我们看一下 JDK8 版本 Object 中的 equals 方法是如何定义的
public boolean equals(Object obj) {
return (this == obj);
}
可以看出,Object 类中的 equals 方法直接使用了 == 来对两个变量进行比较,也就是默认比较的是内存地址。( 这也是为什么 Java 里推荐我们重写 equals 方法,就是让我们自定义比较规则。)
为了更深入地了解 equals,下面我给大家举个例子。首先新建一个 Book 类,附上三个属性和无参有参构造器,注意我这里没有重写 equals 方法
public class Book{
private String name;
private int price;
public Book(){}
public Book(String name, int price){
this.name = name;
this.price = price;
}
}
创建两本 Book 对象进行比较
public class test {
public static void main(String[] args) {
Book book1 = new Book("深入理解 Java 虚拟机", 64.5);
Book book2 = new Book("深入理解 Java 虚拟机", 64.5);
System.out.println(book1.equals(book2)); // false
}
}
可以看出,如果我们没有在 Book 类中重写 Object 中的 equals 方法,那么即使两本书的名字和价格都一样,比较的结果也是 false,原因就是父类 Object 中默认 equals 比较的就是两本 Book 的内存地址。
可我就是想让只要 name、price 两个属性值相等的两本书,比较的结果是相等的,该怎么办?
还能怎么办?那就自定义比较规则,重写 equals!
public class Book{
private String name;
private double price;
public Book(){}
public Book(String name, double price){
this.name = name;
this.price = price;
}
@Override
public boolean equals(Object obj) {
// 如果内存地址都相等,那么两本书就是同一本书,一定相等,返回 true
if(this == obj){
return true;
}
// 判断 obj 是否是 Book 类型
if(obj instanceof Book){
// 到这里说明 obj 确实是一本书,强制类型转换
Book book2 = (Book) obj;
// 判断属性是否相等,如果都相等就返回 true,否则返回 false
return this.name.equals(book2.name) && this.price == book2.price;
}
// 如果 obj 不是书,那两者一定不相等,返回 false
return false;
}
}
先通过 if 条件判断筛选出一些特殊情况,能提高代码执行效率。现在我们再来测试之前的代码,结果会是什么?
public class test {
public static void main(String[] args) {
Book book1 = new Book("深入理解 Java 虚拟机", 64.5);
Book book2 = new Book("深入理解 Java 虚拟机", 64.5);
System.out.println(book1.equals(book2)); // true
}
}
意料之中,结果返回 true!
- 可以看看 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;
}
可以看出 String 类中重写的代码跟我们上面自己重写的代码很相似,先通过 == 判断内存地址是否相等,再判断是否是 String 类型的,层层筛选过后,最后通过遍历 String 底层的 char 数组来判断两个 String 变量的值是否相等。
多阅读源码的好处就是,我们平时的代码规范也可以借鉴这些优秀源码的思想,说不定能让领导大吃一惊哦。现在你学会 == 和 equals 的区别了吗?