核心差異一句話總結
== 比較「記憶體位址」(參考相等),equals() 比較「物件內容」(值相等)。
詳細對比
| 特性 | == | equals() |
| 比較對象 | 參考變數指向的記憶體位址 | 物件的邏輯內容 |
| 適用類型 | 基本型別 + 參考型別 | 僅參考型別(物件) |
| 預設行為 | 位址比較 | Object.equals() 同 ==(位址比較) |
| 可被覆寫 | 不可 | 可(String、Integer、自訂類別皆覆寫) |
| Null 安全 | 可比較 null | 呼叫端為 null 拋 NPE |
基本型別:== 比較值
int a = 100;
int b = 100;
System.out.println(a == b); // true
double x = 0.1 + 0.2;
double y = 0.3;
System.out.println(x == y); // false(浮點數精度問題)
參考型別:== 比較位址
String s1 = new String("Hello");
String s2 = new String("Hello");
System.out.println(s1 == s2); // false(不同物件)
System.out.println(s1.equals(s2)); // true(內容相同)
字串常數池特殊行為
String a = "Hello";
String b = "Hello";
System.out.println(a == b); // true(指向常數池同一物件)
String c = new String("Hello");
System.out.println(a == c); // false
System.out.println(a.equals(c)); // true
包裝類別快取機制
Integer i1 = 100; // 自動裝箱:Integer.valueOf(100)
Integer i2 = 100;
System.out.println(i1 == i2); // true(-128~127 快取)
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i3 == i4); // false(超出快取範圍)
// 正確比較包裝類別
System.out.println(i3.equals(i4)); // true
System.out.println(Objects.equals(i3, i4)); // true(null 安全)
自訂類別正確覆寫 equals()
public class User {
private Long id;
private String name;
// Getter/Setter/建構子略
@Override
public boolean equals(Object o) {
if (this == o) return true; // 同一物件快速回傳
if (o == null || getClass() != o.getClass()) return null檢查與型別檢查
User user = (User) o;
return Objects.equals(id, user.id) && // 使用 Objects.equals 避免 NPE
Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name); // 覆寫 equals 必須覆寫 hashCode
}
}
equals() 契約(規約)
- 自反性:
x.equals(x) 為 true
- 對稱性:
x.equals(y) → y.equals(x)
- 傳遞性:
x.equals(y) && y.equals(z) → x.equals(z)
- 一致性:多次呼叫結果一致(前提物件未修改)
- 非空性:
x.equals(null) 為 false
最佳實踐總結
- 基本型別:用
==
- 物件比較內容:用
equals()
- 可能為 null:用
Objects.equals(a, b)(Java 7+)
- 自訂類別:覆寫
equals() 並同步覆寫 hashCode()
- 字串比較:永遠用
equals() 或 Objects.equals()
- Enum 比較:可用
==(Enum 保證單例)
快速參考表
| 情境 | 推薦寫法 |
| int/double/boolean 等基本型別 | a == b |
| String 比較內容 | a.equals(b) 或 Objects.equals(a, b) |
| Integer/Long 等包裝類別 | a.equals(b) 或 Objects.equals(a, b) |
| 自訂類別 | a.equals(b)(需正確覆寫) |
| Enum | a == b 或 a.equals(b) 皆可 |
| 檢查是否為同一物件實例 | a == b |