Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object

There are multiple problems here, all of them relating to using lombok with inheritance:

  1. 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.

The warning is given by @Data because that usually generates equals/hashcode without the call to super. Fix it by adding @EqualsAndHashCode(callSuper = true).

  1. The @Builder gives you a compile warning because it will generate two static methods with the same name in both the super- and the subclass. Fix it by defining @Builder(builderMethodName = "studentBuilder") on Student.

  2. You won’t be able to set superclass properties on you studentBuilder because your superclass and subclass have a default constructor. Fix it by creating a constructor and moving the @Builder annotation to it (i.e. annotate the constructor with @Builder, not the class):

Code:

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

Call your builder with the correct method (IModel.builder() vs Student.studentBuilder()):

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

I also want to add some improvements to the above solution. While I like lombok as a tool (I really don’t need to read that much boilerplate), the first solution to preventing boilerplate is to think whether you need all those getters and setters and ask yourself these questions:

  • Do you want bags of data? It is fine for some use cases, in others you want objects more in the sense of OOP, i.e. don’t expose your state but behavior.

  • Do you really need mutability? If not, prefer @Value.

  • Do you really need both constructor types (especially the no-args-constructor)? They are part of the problem here. Sometimes you need them for frameworks (proxies, reflection, …) to work properly.

  • More specific to your code: You prefixed the superclass with “I” but it is not an interface. If it is meant as an abstract class, declare it abstract and don’t give it a @Builder.

Leave a Comment