| 比較對象 | == | .equals() |
|---|---|---|
| 基本型別 (int, double, boolean...) | 比較 數值 | 不適用 (基本型別無方法) |
| 引用型別 (物件、陣列、String) | 比較 記憶體位址 (是否同一實例) | 比較 邏輯內容 (取決於類的實現) |
int a = 100, b = 100;
System.out.println(a == b); // true,值相等
// a.equals(b) 編譯錯誤:int 沒有方法
Object o1 = new Object();
Object o2 = new Object();
Object o3 = o1;
System.out.println(o1 == o2); // false,不同實例
System.out.println(o1 == o3); // true,同一實例
System.out.println(o1.equals(o2)); // false,Object.equals 預設也是比地址
String 重寫了 equals() 比較字元序列,但 == 仍比地址。
String s1 = "Monday";
String s2 = "Monday";
System.out.println(s1 == s2); // true!編譯期常量池優化,指向同一對象
System.out.println(s1.equals(s2)); // true
String s1 = "Monday";
String s2 = new String("Monday");
System.out.println(s1 == s2); // false,s2 在堆上新建對象
System.out.println(s1.equals(s2)); // true,內容相同
String s1 = "Monday";
String s2 = new String("Monday");
s2 = s2.intern(); // 檢查常量池是否有 "Monday",有則返回池中引用,無則放入並返回
System.out.println(s1 == s2); // true,s2 現在指向池中對象
System.out.println(s1.equals(s2)); // true
"abc") 自動入池。String.intern():若池中已有內容相同字串,返回池中引用;否則將此字串引用加入池並返回。== 比較 (特定業務場景)。
Integer a = 100; // 自動裝箱 → Integer.valueOf(100)
Integer b = 100;
System.out.println(a == b); // true!-128~127 緩存
Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false,超出緩存範圍新建對象
// 正確比較包裝類別
System.out.println(c.equals(d)); // true
// 或 JDK 7+ Objects.equals(c, d) (空指針安全)
緩存範圍:Byte/Short/Integer/Long 緩存 -128~127;Character 緩存 0~127;Boolean 只有兩個單例 TRUE/FALSE。可通過 -XX:AutoBoxCacheMax= 調整 Integer 緩存上限。
==。.equals() (或 Objects.equals(a,b) 防 NPE)。== (如單例檢查、enum 比較、同步鎖對象)。equals() / equalsIgnoreCase() / contentEquals()。嚴禁用 ==,除非你確定雙邊皆來自常量池/已 intern()。equals() 時必須遵守「自反性、對稱性、傳遞性、一致性、非空性」,並同步覆寫 hashCode()。
@Override
public boolean equals(Object o) {
if (this == o) return true; // 同一實例快速返回
if (o == null || getClass() != o.getClass()) return null; // 類型檢查
MyClass that = (MyClass) o;
return Objects.equals(field1, that.field1) &&
Objects.equals(field2, that.field2) &&
primitiveField == that.primitiveField;
}
@Override
public int hashCode() {
return Objects.hash(field1, field2, primitiveField);
}
== 是「身份識別」,equals() 是「內容平等」。String、包裝類別因常量池/緩存機制導致 == 偶爾返回 true,屬於實現細節副作用,**不可作為業務邏輯依據**。牢記「比內容用 equals,比身份用 ==」,並為自定義類正確實現 equals/hashCode 契約,是寫出健壯 Java 代碼的基礎功夫。