✅ 1. 语法与默认行为
public boolean equals(Object obj) // Object 类中的实现
- 默认实现
仅比较「引用地址」,即this == obj
的结果。
因此,对于两个 new 出来的对象,即使内部字段完全相同,也返回 false。
✅ 2. 何时需要重写
只要业务上需要「按字段内容」判断是否相等(如 String
、Integer
、自定义实体),就必须重写 equals()
。
✅ 3. 重写规则(4 条铁律)
原则 | 说明 |
---|---|
自反性 | x.equals(x) 必为 true |
对称性 | x.equals(y) 与 y.equals(x) 结果一致 |
传递性 | x.equals(y) 且 y.equals(z) ⇒ x.equals(z) |
一致性 | 对象未变,多次调用结果必须相同 |
非空性 | 任何非空对象,x.equals(null) 必须为 false |
✅ 4. 正确重写模板(含 hashCode
)
@Override
public boolean equals(Object o) {
if (this == o) return true; // 1. 同一引用
if (!(o instanceof User)) return false; // 2. 类型检查
User other = (User) o;
return Objects.equals(this.id, other.id) // 3. 关键字段比较
&& Objects.equals(this.name, other.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name); // 4. 同时重写 hashCode
}
⚠️ 重写 equals 必须同时重写 hashCode,否则 HashMap/HashSet 会出错。
✅ 5. 与 ==
的区别
比较符 | 比较内容 | 适用场景 |
---|---|---|
== |
引用地址 | 基本类型或判空 |
equals |
对象「内容」 | 引用类型业务相等判断 |
✅ 6. 空指针安全写法
// 推荐:使用 java.util.Objects 工具类
boolean same = Objects.equals(a, b); // null-safe,不会抛 NPE
✅ 7. 高频坑点汇总
- 只重写 equals 不写 hashCode → Hash 集合行为异常。
- 使用 getClass() 与 instanceof 混用 → 破坏对称性/传递性。
- 在 equals 里修改字段 → 一致性被破坏。
- 把 null 强转后比较字段 → 必抛 NPE。
✅ 8. 一句话总结
默认
equals
比地址,业务相等需重写;重写同时写hashCode
,用Objects.equals
防 NPE。