每天一个注解之:@EqualsAndHashCode

@EqualsAndHashCode是 Lombok 框架提供的注解,用于自动生成类的 equals() 和 hashCode() 方法,且在生成时会包含父类的字段(或父类的 equals()/hashCode() 结果)。

核心作用

Lombok 的 @EqualsAndHashCode 注解默认情况下,生成 equals() 和 hashCode() 时只会考虑当前类的非静态字段,完全忽略父类的字段。而当指定 callSuper = true 时,生成的方法会将父类的字段(或父类的 equals()/hashCode() 结果)纳入判断逻辑,确保子类对象的相等性判断同时依赖父类和子类自身的状态。

具体逻辑

  1. 对 equals() 方法的影响生成的 equals() 会先调用父类的 equals() 方法:

    • 若父类 equals() 返回 false,则直接判定两个对象不相等;
    • 若父类 equals() 返回 true,再继续比较当前类的字段是否相等。
  2. 对 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 相等。

注意事项

  1. 父类需正确实现 equals() 和 hashCode()若父类未重写 equals()(即使用 Object 的默认实现,比较对象引用),则 callSuper = true 可能导致子类 equals() 始终返回 false(除非是同一对象),这通常不符合预期。因此,父类应显式实现 equals() 和 hashCode()(可通过 Lombok 的 @EqualsAndHashCode 简化)。

  2. 避免过度依赖若子类不需要父类字段参与相等性判断(例如父类字段是 “临时状态”),则无需设置 callSuper = true,保持默认即可。

  3. 与 @Data 注解的关系@Data 注解会隐式包含 @EqualsAndHashCode(callSuper = false),因此若子类继承了父类且需要纳入父类字段,需在子类中显式添加 @EqualsAndHashCode(callSuper = true) 以覆盖默认行为。

总结:@EqualsAndHashCode(callSuper = true) 的核心是让子类的 equals() 和 hashCode() 考虑父类状态,确保对象相等性判断的逻辑正确性(尤其是继承场景)。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值