龙目岛等于和哈希码继承 类 与 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
,一切都会按预期进行。
我正在尝试了解 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
,一切都会按预期进行。