Lombok中callSuper=true时继承类equals与hashCode方法未正常匹配的原因咨询
首先,我们来拆解你遇到的核心问题:当你把单一类拆分为继承结构后,使用@EqualsAndHashCode(callSuper=true)时,属性完全一致的子类实例却无法通过equals校验,且hashCode不相等;但callSuper=false时表现正常。
根本原因:父类未生成正确的equals/hashCode方法
你的父类EntityOne仅使用了@Getter、@Setter、@SuperBuilder等注解,但没有添加@EqualsAndHashCode或@Data注解。这意味着:
- Lombok不会为父类生成自定义的
equals和hashCode方法 - 当子类调用
super.equals()和super.hashCode()时,实际上调用的是Object类的默认实现:Object.equals()仅判断两个对象是否为同一引用(内存地址相同)Object.hashCode()返回的是对象的内存地址哈希值
哪怕父类的所有属性完全一致,两个不同的父类实例(子类实例的父类部分)的super.hashCode()也会不同,进而导致子类的整体hashCode不相等;equals判断时,第一步super.equals(other)就会返回false,直接导致整个判断失败。
而你在单一类EntityCombined中使用了@Data注解,它包含@EqualsAndHashCode,Lombok会生成考虑所有属性的equals和hashCode,所以表现符合预期。
为什么callSuper=false时表现正常?
当callSuper=false时,Lombok生成的子类equals和hashCode仅考虑子类自己的属性(也就是你的EntityTwo中的p字段)。你创建的测试实例中p都是默认的null,所以equals返回true、hashCode相等;当p属性不同时,判断失败,这完全符合callSuper=false的设计逻辑。
解决方案:为父类添加@EqualsAndHashCode注解
要让callSuper=true生效,你需要让父类拥有自己的、基于属性的equals和hashCode实现。只需给EntityOne添加@EqualsAndHashCode注解即可:
@AllArgsConstructor @NoArgsConstructor @Getter @Setter @SuperBuilder @EqualsAndHashCode // 新增这个注解 public class EntityOne { // 原有属性和枚举代码不变 }
如果父类适合用@Data(比如不需要自定义构造器逻辑),也可以直接替换为@Data(@Data包含@EqualsAndHashCode、@Getter、@Setter等),注意调整构造器注解的冲突(@Data会生成@RequiredArgsConstructor,如果需要无参和全参构造器,仍需保留@NoArgsConstructor和@AllArgsConstructor):
@NoArgsConstructor @AllArgsConstructor @Data @SuperBuilder public class EntityOne { // 原有属性和枚举代码不变 }
添加后,子类调用super.equals()时,会使用父类生成的、基于属性的判断逻辑,结合子类自己的属性校验,就能像单一类那样实现正确的equals和hashCode判断了。
内容的提问来源于stack exchange,提问作者gringogordo

