面試官:請問 equals() 和 "==" 有什麼區別?
應聘者:
-
equals()方法用來比較的是兩個物件的內容是否相等,由於所有的類都是繼承自java.lang.Object類的,所以適用於所有物件,如果沒有對該方法進行覆蓋的話,呼叫的仍然是Object類中的方法,而Object中的equals方法返回的卻是==的判斷;
-
"==" 比較的是變數(棧)記憶體中存放的物件的(堆)記憶體地址,用來判斷兩個物件的地址是否相同,即是否是指相同一個物件。
equals()作用
equals() 的作用是用來判斷兩個物件是否相等。
equals() 定義在JDK的Object.java中。通過判斷兩個物件的地址是否相等(即,是否是同一個物件)來區分它們是否相等。原始碼如下:
public boolean equals(Object obj) {
return (this == obj);
}
既然Object.java中定義了equals()方法,這就意味著所有的Java類都實現了equals()方法,所有的類都可以通過equals()去比較兩個物件是否相等。但是,我們已經說過,使用預設的“equals()”方法,等價於“==”方法。因此,我們通常會重寫equals()方法:若兩個物件的內容相等,則equals()方法返回true;否則,返回fasle。
下面根據"類是否覆蓋equals()方法",將它分為2類。
-
若某個類沒有覆蓋equals()方法,當它的通過equals()比較兩個物件時,實際上是比較兩個物件是不是同一個物件。這時,等價於通過“==”去比較這兩個物件。
-
我們可以覆蓋類的equals()方法,來讓equals()通過其它方式比較兩個物件是否相等。通常的做法是:若兩個物件的內容相等,則equals()方法返回true;否則,返回fasle。
下面,舉例對上面的2種情況進行說明:
沒有覆蓋equals()方法的情況
public class EqualsTest {
public static void main(String[] args) {
// 新建2個相同內容的Person物件,
// 再用equals比較它們是否相等
User user1 = new User("James", 100);
User user2 = new User("James", 100);
System.out.printf("比較結果:" + user1.equals(user2));
}
/**
* @desc User類。
*/
static class User {
int age;
String name;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return name + " - " + age;
}
}
}
執行結果:
比較結果:false
結果分析:我們通過 user1.equals(user2) 來“比較user1和user2是否相等時”。實際上,呼叫的Object.java的equals()方法,即呼叫的 (user1==user2) 。它是比較“p1和p2是否是同一個物件”。而由 user1 和 user2 的定義可知,它們雖然內容相同;但它們是兩個不同的物件,因此,返回結果是false。
覆蓋equals()方法的情況
修改上面的EqualsTest,覆蓋equals()方法:
public class EqualsTest {
public static void main(String[] args) {
// 新建2個相同內容的Person物件,
// 再用equals比較它們是否相等
User user1 = new User("James", 100);
User user2 = new User("James", 100);
System.out.printf("比較結果:" + user1.equals(user2));
}
/**
* @desc User類。
*/
static class User {
int age;
String name;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return name + " - " + age;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
}
執行結果:
比較結果:true
結果分析:我們在EqualsTest.java 中重寫了User的equals()函式:當兩個User物件的 name 和 age 都相等,則返回true。因此,執行結果返回true。
== 的作用
“==”:它的作用是判斷兩個物件的地址是不是相等。即判斷引用物件是不是指向的堆中的同一個物件,我們知道,凡是new出來的物件都在堆中。而物件的引用都存放在棧中,具體來講就是放在棧幀中,我們來看下面一段程式碼:
public static void main(String[] args) {
User user1 = new User("James", 100);
User user2 = new User("James", 100);
System.out.println("user1.equals(user2):" + user1.equals(user2));
System.out.println("user1==user2:" + (user1==user2));
}
輸出結果:
user1.equals(user2):true
user1==user2:false
用記憶體圖表示如下:
指向的是堆中兩塊不同的區域,所以用 "==" 比較時返回的是false。