正确编写 equals 和 hashCode 的核心是逻辑一致、遵守五条规则(自反、对称、传递、一致、非空)且字段完全匹配;推荐用 IDE 自动生成或 Lombok 注解,避免手动出错。

在 Java 中正确编写 equals 和 hashCode 方法,核心是保证二者逻辑一致、满足约定,并适配业务场景。不重写或错误实现会导致集合(如 HashMap、HashSet)行为异常,比如对象“明明相等却查不到”或“重复添加”。
equals 方法必须遵守的五条规则
Java 规范要求 equals 是自反性、对称性、传递性、一致性、非空性的。实际编码中容易出错的是后三条:
-
对称性:若
a.equals(b)为true,则b.equals(a)也必须为true;避免在子类中用instanceof判类型时破坏它(推荐用getClass() == obj.getClass()) -
传递性:若
a.equals(b)且b.equals(c),则a.equals(c)必须成立;继承结构复杂时,用getClass()比instanceof更安全 -
一致性:只要参与比较的字段没变,多次调用结果应相同;不要在
equals中依赖可变状态(如当前时间、随机数) - 注意
null安全:开头加if (obj == null) return false;,再用getClass()或instanceof判断类型
hashCode 方法的关键原则
hashCode 不必唯一,但必须保证:如果两个对象 equals 返回 true,它们的 hashCode 必须相等。反之不成立(哈希冲突允许)。常见写法:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 用
Objects.hash(...)最简洁安全,自动处理null;例如:return Objects.hash(id, name, age); - 手动计算时,初始值通常取
1或31,每步用result = 31 * result + field.hashCode();字符串、包装类直接调.hashCode(),基本类型用Boolean.hashCode()等静态方法 - 参与
hashCode计算的字段,必须和equals中用于比较的字段完全一致——这是最容易忽略的一致性要求
推荐写法:用 IDE 自动生成或 Lombok
手写易错,优先借助工具:
立即学习“Java免费学习笔记(深入)”;
- IntelliJ / Eclipse:右键 → Generate →
equals()andhashCode(),勾选需要参与比较的字段即可,生成代码符合规范 - Lombok:加注解
@EqualsAndHashCode,默认包含所有非静态非瞬态字段;可指定include或exclude字段,例如:@EqualsAndHashCode(onlyExplicitlyIncluded = true)配合@EqualsAndHashCode.Include - 注意:若类有继承关系,Lombok 默认只处理当前类字段;需显式配置
callSuper = true并确保父类也有合规实现
特殊场景注意事项
某些业务逻辑会让默认策略失效,需人工干预:
-
数据库主键未赋值时:新建对象 ID 为
null或0,若直接参与比较,多个新对象会相互equals;建议仅比对业务唯一标识(如手机号、邮箱),或使用 UUID 作为临时 ID -
浮点数字段:避免直接用
==比较double/float;改用Double.compare(a, b) == 0或Math.abs(a - b) -
集合/数组字段:用
Objects.equals(list1, list2)或Arrays.equals(arr1, arr2),别用==或list1.equals(list2)(后者可能因实现不同行为不一致)

















