生成 equals/hashCode 实现,但不调用超类,即使此类不扩展 java.lang.Object

2022-09-01 14:05:54

我在使用时遇到以下错误,甚至不允许我在创建实例时设置id和版本。lombokstudent

Multiple markers at this line
    - overrides com.example.demo.IModel.canEqual
    - Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is 
     intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
    - overrides com.example.demo.IModel.hashCode
    - overrides com.example.demo.IModel.toString
    - overrides com.example.demo.IModel.equals

IModel

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class IModel {
    private String id;
    private String version;
}

学生

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student extends IModel{
    private String firstName;
    private String lastName;
}

enter image description here

在main方法中,它不允许我设置Id和版本字段的值

Student s = Student.builder().firstName("Adam").lastName("Kerr").build();

Edit-1 @sfiss - 按照建议,现在我更改了如下,但现在我无法设置名字和姓氏,只能设置驾驶室ID和版本

学生.java

@Data
@Builder(builderMethodName = "studentBuilder")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class Student extends IModel {
    @NotEmpty(message = "{email.notempty}")
    @Email
    private String firstName;
    private String lastName;

    public Student(final String firstName, final String lastName, final String id, final String version) {
        super(id, version);
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

IModel.java

@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class IModel {
    private String id;
    private String version;
}

答案 1

这里存在多个问题,所有这些问题都与使用龙目岛进行继承有关:

  1. 生成 equals/hashCode 实现,但不调用超类,即使此类不扩展 java.lang.Object。如果这是故意的,请将“@EqualsAndHashCode(callSuper=false)”添加到您的类型中。

警告是由 给出的,因为它通常会生成等于/哈希码,而无需调用 super。通过添加 .@Data@EqualsAndHashCode(callSuper = true)

  1. 会给您一个编译警告,因为它将在超类和子类中生成两个同名的静态方法。通过在 上定义 来修复它。@Builder@Builder(builderMethodName = "studentBuilder")Student

  2. 您将无法在 studentBuilder 上设置超类属性,因为您的超类和子类具有默认构造函数。通过创建一个构造函数并将注释移动到它来修复它(即@Builder而不是类来注释构造函数):@Builder

法典:

@Builder(builderMethodName = "studentBuilder")
public Student(
    final String firstName,
    final String lastName,
    final String id,
    final String version) {
    super(id, version);
    this.firstName = firstName;
    this.lastName = lastName;
}

使用正确的方法(vs)调用您的构建器:IModel.builder()Student.studentBuilder()

Student.studentBuilder().firstName("Name").build();

我还想对上述解决方案进行一些改进。虽然我喜欢龙目岛作为一种工具(我真的不需要阅读那么多样板),但防止样板的第一个解决方案是思考你是否需要所有这些 getter 和 setter,并问自己以下问题:

  • 你想要一袋袋数据吗?对于某些用例来说,这很好,在其他用例中,您希望对象更多地处于OOP的意义上,即不公开您的状态,而是暴露行为。

  • 你真的需要可变性吗?如果没有,则首选 .@Value

  • 你真的需要这两种构造函数类型(尤其是无参数构造函数)吗?他们是这里问题的一部分。有时,您需要它们来使框架(代理,反射等)正常工作。

  • 更具体地说明您的代码:您在超类前面加上了“I”前缀,但它不是一个接口。如果它意味着一个抽象类,请声明它,不要给它一个.abstract@Builder


答案 2

您可以使用@sfiss解决方案

您可以使用 和 批注而不是批注。@Getter@Setter@Data


推荐