龙目岛等于和哈希码继承 类 与 callsuper=true

Lombok equals and hash code on inherited classes with callsuper=true

我正在尝试了解 lombok equals 对象方法如何适用于继承的 classes。我看过 this 但仍然不完全理解 ...

如果我创作这首单曲class

@AllArgsConstructor
@NoArgsConstructor
@Data
@SuperBuilder
public class EntityCombined {

    @Builder.Default
    private List<@Valid EntityFour> aList = new ArrayList<>();

    @Size(min = 5)
    private String a;

    @NotNull
    private EntityThree.Type b;
    @NotNull
    private String           c;
    @CountryCode2
    private String    d;
    @NotNull
    private boolean   e;
    @NotNull
    private boolean   f;
    @NotNull
    private boolean   g;

    public enum Type {
        Q, W, E, R, T, Y
    }

    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    @Builder
    public static
    class EntityFour {
        @NotNull
        private String  a;
        @CountryCode2
        private String  b;
        @NotNull
        private boolean c;
    }
}

一切如我所料,

final EntityCombined ec1 = StaticContentProvider.createEntityCombined();
final EntityCombined ec2 = StaticContentProvider.createEntityCombined();
final EntityCombined ec3 = StaticContentProvider.createAnotherEntityCombined();

//pass
assertEquals(ec1.hashCode(), ec2.hashCode());
assertEquals(ec1, ec2);
assertTrue(ec1.equals(ec2));

//fail
assertEquals(ec1.hashCode(), ec3.hashCode());
assertEquals(ec1, ec3);
assertTrue(ec1.equals(ec3));

但是,如果我将它拆分成这样的继承 class 结构(我注释掉了内部 class 以检查这不是问题所在)

@NoArgsConstructor
@Data
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
public class EntityTwo extends EntityOne {

    private String p;

//    @Builder.Default
//    private List<@Valid EntityFour> aList = new ArrayList<>();

//    @AllArgsConstructor
//    @NoArgsConstructor
//    @Data
//    @Builder
//    public static
//    class EntityFour {
//        @NotNull
//        private String  a;
//        @CountryCode2
//        private String  b;
//        @NotNull
//        private boolean c;
//    }
}

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@SuperBuilder
public class EntityOne {

    @Size(min = 5)
    private String a;

    @NotNull
    private Type b;
    @NotNull
    private String    c;
    @CountryCode2
    private String    d;
    @NotNull
    private boolean   e;
    @NotNull
    private boolean   f;
    @NotNull
    private boolean   g;

    public enum Type {
        Q, W, E, R, T, Y
    }
}

并像这样初始化

final EntityTwo local21 = new EntityTwo().builder()
        .a("hello")
        .b(EntityTwo.Type.Q)
        .e(true)
        .f(true)
        .g(true)
        .c("qwasty")
        .d("Let's be avenue")
        .build();
final EntityTwo local22 = new EntityTwo().builder()
        .a("hello")
        .b(EntityTwo.Type.Q)
        .e(true)
        .f(true)
        .g(true)
        .c("qwasty")
        .d("Let's be avenue")
        .build();;
final EntityTwo local23 = new EntityTwo().builder()
        .a("diff")
        .b(EntityTwo.Type.Q)
        .e(true)
        .f(true)
        .g(true)
        .c("qwasty")
        .d("Let's be avenue")
        .build();

然后 callsuper = true 相同的对象不匹配

assertEquals(local21.hashCode(), local22.hashCode());
assertEquals(local21, local22);
assertTrue(local21.equals(local22));

全部失败。

如果我设置 callSuper = false 那么它们都会匹配(除非我将 p 设置为不同)。这对我来说很有意义,但我不明白为什么 callsuper = true 它不仅仅是将它们视为 'flat class' 像 EntityCombined?

我可以定义自己的等号运算符,所以这不是什么大问题,但我想了解为什么它们不匹配,或者想知道我是否在某些方面弄错了配置?

您在 EntityOne 上没有 @EqualsAndHashCode。这意味着 EntityOne 使用 Object 中的 equals 逻辑,它只检查引用相等性。这意味着两个不同的对象将始终不相等,即使它们共享相同的字段值。 EntityTwo 中的 lombok-generated equals() 调用 EntityOne::equals 因为你通过 @EqualsAndHashCode(callSuper = true) 告诉了 lombok。 (请记住,lombok 的代码只处理注释 class 中的内容,即 equals() 只比较注释 class 中的字段,而不比较 superclass 中的字段。 )

只需将 @EqualsAndHashCode 添加到 EntityOne,一切都会按预期进行。