@EqualsAndHashCode是 Lombok 框架提供的注解,用于自动生成类的 equals() 和 hashCode() 方法,且在生成时会包含父类的字段(或父类的 equals()/hashCode() 结果)。
核心作用
Lombok 的 @EqualsAndHashCode 注解默认情况下,生成 equals() 和 hashCode() 时只会考虑当前类的非静态字段,完全忽略父类的字段。而当指定 callSuper = true 时,生成的方法会将父类的字段(或父类的 equals()/hashCode() 结果)纳入判断逻辑,确保子类对象的相等性判断同时依赖父类和子类自身的状态。
具体逻辑
-
对
equals()方法的影响生成的equals()会先调用父类的equals()方法:- 若父类
equals()返回false,则直接判定两个对象不相等; - 若父类
equals()返回true,再继续比较当前类的字段是否相等。
- 若父类
-
对
hashCode()方法的影响生成的hashCode()会将父类的hashCode()结果与当前类字段的哈希值组合(通过按位异或等方式),确保哈希值同时反映父类和子类的状态。
为什么需要 callSuper = true?
默认情况下(callSuper = false),Lombok 生成的 equals() 和 hashCode() 会忽略父类字段,可能导致逻辑错误。例如:
// 父类
class Person {
protected String name;
// 省略构造器、getter等
}
// 子类(默认 callSuper = false)
@EqualsAndHashCode
class Student extends Person {
private int studentId;
// 省略构造器、getter等
}
此时,两个 Student 对象即使 name 不同(父类字段),只要 studentId 相同,equals() 就会返回 true,这显然不符合 “对象相等” 的预期(因为 name 是身份的重要部分)。
正确用法示例
若希望 Student 的相等性同时依赖父类 name 和自身 studentId,需显式指定 callSuper = true:
// 父类:建议手动实现或用 @EqualsAndHashCode
class Person {
protected String name;
// 手动实现 equals 和 hashCode(或加 @EqualsAndHashCode)
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
// 子类:包含父类字段的判断
@EqualsAndHashCode(callSuper = true) // 关键:纳入父类的 equals/hashCode
class Student extends Person {
private int studentId;
// Lombok 会自动生成 equals 和 hashCode,逻辑为:
// equals:先调用 super.equals(o),再比较 studentId
// hashCode:super.hashCode() 与 studentId 的哈希值组合
}
此时,两个 Student 对象相等的条件是:
- 父类
name相等(通过super.equals()验证); - 自身
studentId相等。
注意事项
-
父类需正确实现
equals()和hashCode()若父类未重写equals()(即使用Object的默认实现,比较对象引用),则callSuper = true可能导致子类equals()始终返回false(除非是同一对象),这通常不符合预期。因此,父类应显式实现equals()和hashCode()(可通过 Lombok 的@EqualsAndHashCode简化)。 -
避免过度依赖若子类不需要父类字段参与相等性判断(例如父类字段是 “临时状态”),则无需设置
callSuper = true,保持默认即可。 -
与
@Data注解的关系@Data注解会隐式包含@EqualsAndHashCode(callSuper = false),因此若子类继承了父类且需要纳入父类字段,需在子类中显式添加@EqualsAndHashCode(callSuper = true)以覆盖默认行为。
总结:@EqualsAndHashCode(callSuper = true) 的核心是让子类的 equals() 和 hashCode() 考虑父类状态,确保对象相等性判断的逻辑正确性(尤其是继承场景)。
8854

被折叠的 条评论
为什么被折叠?



