重写 equals 方法必须遵守自反性、对称性、传递性、一致性及与 null 比较返回 false 五原则,且须同步重写 hashCode;推荐用 IDE 自动生成或 Objects.hash 简化实现,注意判空、类型检查用 getClass()、字段比较用 Objects.equals。

重写 equals 方法不是简单地比较字段值,而是要遵守 Java 规范定义的五个核心原则:自反性、对称性、传递性、一致性、与 null 比较返回 false。否则可能引发集合类(如 HashMap、HashSet)行为异常或逻辑 bug。
必须同时重写 hashCode
如果只重写 equals 而不重写 hashCode,会导致对象在哈希集合中无法正确查找或去重。Java 规定:两个逻辑相等的对象(equals 返回 true),其 hashCode 必须相同。
- 推荐用 IDE 自动生成(如 IntelliJ 的
Alt+Insert→ “Generate…” → “equals() and hashCode()”) - 手动写时,确保
hashCode计算覆盖了equals中所有参与比较的字段 - 可用
Objects.hash(field1, field2, ...)简化实现
标准重写步骤(以 Person 类为例)
假设 Person 有 name(String)、age(int)、id(Long)三个字段,判断“业务上相等”即这三个字段完全一致:
-
第一步:检查是否为同一对象 ——
if (this == obj) return true; -
第二步:判空 + 类型检查 ——
if (obj == null || getClass() != obj.getClass()) return false;(注意用getClass()而非instanceof,避免子类不对称问题) -
第三步:类型转换 ——
Person person = (Person) obj; -
第四步:逐字段比较 —— 基本类型用
==,引用类型用Objects.equals(a, b)(自动处理null)
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age
&& Objects.equals(name, person.name)
&& Objects.equals(id, person.id);
}
常见错误和避坑点
-
忘记判空:直接调用
obj.field.equals(...)可能抛NullPointerException -
用
==比较字符串或包装类:应统一用Objects.equals(str1, str2) -
子类继承时用
instanceof:会导致对称性被破坏(A.equals(B) 为 true,但 B.equals(A) 为 false) -
修改了参与
equals比较的字段后,对象还留在HashSet或作为HashMap的 key:将无法再被查到,因为哈希桶位置已变


















