【问题标题】:Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object生成 equals/hashCode 实现但没有调用超类,即使这个类没有扩展 java.lang.Object
【发布时间】:2019-10-28 05:17:45
【问题描述】:

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

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

模型

@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;
}

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

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

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

Student.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;
}

【问题讨论】:

  • 我不同意(它不是重复的),这个问题也有使用@Builder继承的问题。它的名字很糟糕,显然问题没有被 OP 正确识别。

标签: java lombok


【解决方案1】:

这里有多个问题,所有这些问题都与使用 lombok 和继承有关:

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

警告由@Data 给出,因为这通常会在不调用 super 的情况下生成 equals/hashcode。通过添加@EqualsAndHashCode(callSuper = true) 来修复它。

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

  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;
}

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

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

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

  • 您想要数据包吗?对于某些用例来说这很好,而在其他用例中,您需要更多 OOP 意义上的对象,即不要暴露您的状态而是行为。

  • 您真的需要可变性吗?如果没有,请选择@Value

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

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

【讨论】:

  • 感谢您的出色回答,但我仍然面临问题,请参阅 EDIT-1
  • 查看我编辑的答案。简而言之:1) 使用正确的构建器工厂方法和 2) 注释构造器,该构造器具有您在构建器中所需的所有所需字段。
【解决方案2】:

你可以使用@sfiss解决方案

您可以使用@Getter@Setter 注释代替@Data 注释。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    相关资源
    最近更新 更多