equals和hashcode必须同时重写以保证逻辑一致:equals相等则hashcode必相同,否则hashmap等集合会失效;equals需满足自反性、对称性、传递性、一致性、非空性五契约;重写时先判引用、再判null、再判类型、最后比较字段;hashcode必须仅用equals中涉及的字段计算,且保持不变性。

面试中问到 equals 和 hashCode 怎么同时重写,核心不是背代码,而是讲清逻辑一致性——只要 equals 认为相等,hashCode 就必须返回相同值;否则 HashMap、HashSet 会“找不到”或“重复存”。
equals 方法必须满足五条契约
面试官常会追问“你写的 equals 是否合规”,所以别只写字段比较,得守住底线:
- 自反性:obj.equals(obj) 必须返回 true
- 对称性:obj1.equals(obj2) 和 obj2.equals(obj1) 结果一致
- 传递性:若 obj1.equals(obj2) && obj2.equals(obj3),则 obj1.equals(obj3) 也得为 true
- 一致性:多次调用结果不变(对象状态未变的前提下)
- 非空性:obj.equals(null) 必须返回 false
重写 equals 的标准步骤
手写时按顺序来,漏一步都可能出 Bug:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 先用 this == obj 判断是否同一引用(性能快,且满足自反性)
- 再判 obj == null(保非空性)
- 用 getClass() != obj.getClass() 检查类型(不用 instanceof,避免子类破坏对称性)
- 强制转型后,逐个比较参与业务相等判断的关键字段(String 用 Objects.equals,基本类型用 ==,包装类注意 null)
hashCode 必须和 equals 严格对齐
这是面试最易翻车的点。错配后果直接:set.add(a); set.contains(b) 返回 false,即使 a.equals(b) 是 true。
- 所有在 equals 中参与比较的字段,一个都不能少地参与 hashCode 计算
- 不要在 hashCode 里加额外字段(虽不报错,但违反契约,未来改 equals 时极易漏同步)
- 避免调用可能抛异常或返回可变值的方法(比如懒加载 getter、数据库查询方法)
- 推荐用 IDE 自动生成(IntelliJ → Alt+Insert → “equals() and hashCode()”),它能自动覆盖 null 安全、字段一致性、常量种子等细节
常见踩坑场景(面试加分项)
说出这些,说明你真踩过坑、调过问题:
- 可变字段当 key:对象放进 HashMap 后改了 equals 字段,再 get 就找不到——因为哈希桶位置变了,但旧值还留在原桶里
- 继承场景没处理好:父类重写了 equals,子类新增字段但没重写,导致对称性被破坏
- 用了 Lombok @EqualsAndHashCode 但 exclude 了关键字段,或没设 onParam = _ 保证 null 安全
- 时间字段用 new Date() 直接比较,精度问题导致 equals 返回 false,而数据库查出来却是同一条
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










