Lombok:等于子类中的字符串实例变量
Lombok: Equals for string instance variables in subclass
我最近偶然发现 Lombok
并想测试它,当我 运行 遇到这个小问题时。
假设我有
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Name extends AbstractName {
@NonNull
private String firstname;
@NonNull
private String lastname;
}
其中 AbstractName
是空摘要 class。我想用
测试 equals
方法
@Test
public void testEquals() {
Name instance1 = new Name("Vorname","Nachname");
Name instance2 = new Name("Vorname","Nachname");
boolean expResult = true;
boolean result = instance1.equals(instance2);
assertEquals(expResult, result);
}
如您所见,我希望 Name
的两个实例相等。如果你添加
System.out.println(instance1.getFirstname().equals(instance2.getFirstname()));
System.out.println(instance1.getLastname().equals(instance2.getLastname()));
一个得到
true
true
那么,为什么测试失败了?是继承AbstractName
的hashCode()
问题吗?我该如何解决?
顺便说一句,它不会失败,如果 Name
是一个独立的 class 而不是 AbstractName
的子 class。
原版 Java
这是 Lombok
创建的代码
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Name)) return false;
final Name other = (Name) o;
if (!other.canEqual((java.lang.Object) this)) return false;
if (!super.equals(o)) return false;
final java.lang.Object this$firstname = this.getFirstname();
final java.lang.Object other$firstname = other.getFirstname();
if (this$firstname == null ? other$firstname != null : !this$firstname.equals(other$firstname)) return false;
final java.lang.Object this$lastname = this.getLastname();
final java.lang.Object other$lastname = other.getLastname();
if (this$lastname == null ? other$lastname != null : !this$lastname.equals(other$lastname)) return false;
return true;
}
使用@Data 是一种快捷方式,其中包括@EqualsAndHashCode。尝试显式添加 @EqualsAndHashCode 并将 callSuper
设置为 false。
但是,对于 long-term 维护,覆盖基础 class 中的 equals/hashCode 和 return true/0 可能更安全,或者应用 @ EqualsAndHashCode 为基数 class.
那么,为什么测试失败了呢?是不是继承了AbstractName导致的hashCode()问题?我该如何解决?
顺便说一句,它不会失败,如果 Name 是独立的 class 而不是 AbstractName
的子class
详细说明为什么当 callSuper 为 True 时测试会失败。
假设您有一个 Child class,它扩展了一个抽象 class。 (或与此相关的任何其他 class)
Name.java:
@EqualsAndHashCode(callSuper = true)
public class Name extends AbstractName {
摘要Name.java:
public class AbstractName {
//some fields
现在,当我们比较具有相同值的 Name.java 的 2 个实例时,因为我们正在使用 Name.java 中的 @EqualsAndHashCode
lombok 注释覆盖 equals() 和 hashcode() 方法,所以正确检查值。但是由于我们没有覆盖 AbstractName.java 中的 equals() 和 hashcode() 方法,所以默认情况下 equals() 将始终失败,即使属性的值相同(除非 AbstractName 的 object实例指向相同的 object 引用)
因此,一种选择是在 Child class 中制作 @EqualsAndHashCode(callSuper = false)
。但是parentclass(AbstractName.java)中的字段不会被比较
解决方案:- 更好的选择是在 Name.java 中添加 @EqualsAndHashCode(callSuper = true)
并在 AbstractName.java 中添加 @EqualsAndHashCode
以便覆盖 equals() 和 hashcode()在 parent 和 child class 中,以便正确比较所有 class 中的字段
我最近偶然发现 Lombok
并想测试它,当我 运行 遇到这个小问题时。
假设我有
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Name extends AbstractName {
@NonNull
private String firstname;
@NonNull
private String lastname;
}
其中 AbstractName
是空摘要 class。我想用
equals
方法
@Test
public void testEquals() {
Name instance1 = new Name("Vorname","Nachname");
Name instance2 = new Name("Vorname","Nachname");
boolean expResult = true;
boolean result = instance1.equals(instance2);
assertEquals(expResult, result);
}
如您所见,我希望 Name
的两个实例相等。如果你添加
System.out.println(instance1.getFirstname().equals(instance2.getFirstname()));
System.out.println(instance1.getLastname().equals(instance2.getLastname()));
一个得到
true
true
那么,为什么测试失败了?是继承AbstractName
的hashCode()
问题吗?我该如何解决?
顺便说一句,它不会失败,如果 Name
是一个独立的 class 而不是 AbstractName
的子 class。
原版 Java
这是 Lombok
@java.lang.Override
@java.lang.SuppressWarnings("all")
@lombok.Generated
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Name)) return false;
final Name other = (Name) o;
if (!other.canEqual((java.lang.Object) this)) return false;
if (!super.equals(o)) return false;
final java.lang.Object this$firstname = this.getFirstname();
final java.lang.Object other$firstname = other.getFirstname();
if (this$firstname == null ? other$firstname != null : !this$firstname.equals(other$firstname)) return false;
final java.lang.Object this$lastname = this.getLastname();
final java.lang.Object other$lastname = other.getLastname();
if (this$lastname == null ? other$lastname != null : !this$lastname.equals(other$lastname)) return false;
return true;
}
使用@Data 是一种快捷方式,其中包括@EqualsAndHashCode。尝试显式添加 @EqualsAndHashCode 并将 callSuper
设置为 false。
但是,对于 long-term 维护,覆盖基础 class 中的 equals/hashCode 和 return true/0 可能更安全,或者应用 @ EqualsAndHashCode 为基数 class.
那么,为什么测试失败了呢?是不是继承了AbstractName导致的hashCode()问题?我该如何解决? 顺便说一句,它不会失败,如果 Name 是独立的 class 而不是 AbstractName
的子class详细说明为什么当 callSuper 为 True 时测试会失败。
假设您有一个 Child class,它扩展了一个抽象 class。 (或与此相关的任何其他 class)
Name.java:
@EqualsAndHashCode(callSuper = true)
public class Name extends AbstractName {
摘要Name.java:
public class AbstractName {
//some fields
现在,当我们比较具有相同值的 Name.java 的 2 个实例时,因为我们正在使用 Name.java 中的 @EqualsAndHashCode
lombok 注释覆盖 equals() 和 hashcode() 方法,所以正确检查值。但是由于我们没有覆盖 AbstractName.java 中的 equals() 和 hashcode() 方法,所以默认情况下 equals() 将始终失败,即使属性的值相同(除非 AbstractName 的 object实例指向相同的 object 引用)
因此,一种选择是在 Child class 中制作 @EqualsAndHashCode(callSuper = false)
。但是parentclass(AbstractName.java)中的字段不会被比较
解决方案:- 更好的选择是在 Name.java 中添加 @EqualsAndHashCode(callSuper = true)
并在 AbstractName.java 中添加 @EqualsAndHashCode
以便覆盖 equals() 和 hashcode()在 parent 和 child class 中,以便正确比较所有 class 中的字段