@equalsandhashcode能自动生成符合java契约的equals和hashcode方法,需注意callsuper=true处理继承、用exclude/of控制字段参与,避免集合异常。

用 Lombok 的 @EqualsAndHashCode 注解,能直接省掉手写 equals 和 hashCode 的全部模板代码,同时严格遵守 Java 的契约要求——只要字段选对、继承处理得当,生成的方法就可靠可用。
为什么必须一起处理这两个方法
Java 规定:如果 a.equals(b) 返回 true,那么 a.hashCode() 必须等于 b.hashCode()。这是 HashMap、HashSet 等集合正常工作的前提。只重写 equals 不重写 hashCode,或者两者逻辑不一致,会导致:
- 同一个业务对象在 HashSet 中被当作两个不同元素存入
- HashMap 里用 key 查不到已存的 value
- 对象在集合中“消失”或重复,问题隐蔽难定位
@EqualsAndHashCode 的基础用法
加在类上,Lombok 就会基于所有非静态、非 transient 字段自动生成两个方法:
- 默认包含当前类全部可比字段(不含父类)
- 生成的 equals 会做空值检查、类型校验、字段逐一对比
- hashCode 使用 Objects.hash(field1, field2...) 计算,天然满足契约
示例:
@EqualsAndHashCode
public class User {
private String id;
private String name;
}
继承场景下关键参数 callSuper = true
子类继承了带业务字段的父类时,必须显式设置 callSuper = true,否则父类字段会被忽略:
- callSuper = false(默认):只比较子类字段,父类字段不参与判断
- callSuper = true:先调用父类的 equals/hashCode,再叠加子类字段
- 若父类也用了 @EqualsAndHashCode,那整个链路就完整覆盖
错误示范(可能导致两个逻辑不同的对象被判定为相等):
@EqualsAndHashCode // 漏掉 callSuper = truepublic class AdminUser extends User {
private String role;
}
按需控制参与比较的字段
不是所有字段都该影响对象相等性。比如创建时间、版本号、缓存字段通常应排除:
- 排除某些字段:exclude = {"createTime", "version"}
- 只保留指定字段:of = {"id"} 或 of = {"code", "tenantId"}
- exclude 和 of 不能同时使用,选其一即可
常见用途:DTO 与实体混用时,用 of 精确锁定主键;审计字段多的类,用 exclude 避免干扰。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











