How to use Lombok @SuperBuilder on Abstract classes with final fields

≯℡__Kan透↙ 提交于 2020-03-04 17:45:46

问题


Given the following classes with the Lombok annotations @Data and @SuperBuilder

@Data
@SuperBuilder
public abstract class Parent {

    protected final String userId;
    protected final Instant requestingTime;
}

@Data
@SuperBuilder
public class Child extends Parent {

    private final Instant beginningDate;
    private final Instant endingDate;
    private final Collection<String> fields;
}

I am getting the following error appearing over the @Data annotation in the Child class:

Implicit super constructor Parent() is undefined. Must explicitly invoke another constructor.

Is there a way to configure a non-default constructor on the Child class's @Data annotation in order to have all final fields on both the Child and Parent classes initialized when invoking the Builder?

I have tried a few different combinations of the @Data, @Getter, @Setter annotations with the @SuperBuilder annotation on both the child and parent classes, but haven't found a working solution yet. I am using Lombok 1.18.10.

For reference, this question is related

EDIT

This is effectively the constructor that Lombok should be constructing and invoking on the SuperBuilder.build() operation.

public Child(
    final String userId,
    final Instant requestingTime,
    final Instant beginningDate,
    final Instant endingDate,
    final Collection<String> fields) {

    super(userId, requestingTime);
    this.beginningDate = beginningDate;
    this.endingDate = endingDate;
    this.fields= fields;
}

As requested, this is how I would expect to invoke the builder on the Child object.

final Child child = Child.Builder()
                         .userId(<value>)
                         .requestingTime(<value>)
                         .beginningDate(<value>)
                         .endingDate(<value>)
                         .fields(<value>)
                         .build();

回答1:


AFAIK, @Data generates a @NoArgsConstructor, which is just wrong. Actually, @Data is wrong per se, as it's meant for mutable classes; @Value would be better, but it can't deal with the super constructor either.

So remove @Data, add @Getter, @EqualsAndHashCode, @ToString and whatever you need. Don't forget to add callSuper=true in the subclass.


This is effectively the constructor that Lombok should be constructing and invoking on the SuperBuilder.build() operation.

public Child(
    final String userId,
    final Instant requestingTime,
    final Instant beginningDate,
    final Instant endingDate,
    final Collection<String> fields) {

    super(userId, requestingTime);
    this.beginningDate = beginningDate;
    this.endingDate = endingDate;
    this.fields= fields;
}

No, that's not how SuperBuilder works. This is actually Lombok can't do as it can't see the super fields. Instead, the builder uses something like

public Child(ChildBuilder b) {    
    super(b);
    this.beginningDate = b.beginningDate;
    this.endingDate = b.endingDate;
    this.fields= b.fields;
}

You can believe what Jan Rieke says, he wrote it.




回答2:


@Data annotation implicitly generate code for below mentioned functionalities:


  • setter
  • getter
  • toString
  • equallAndHashCode
  • constructor(for required arguments only)

It means constructor declaration of loombok will generate code for Parent class will be as mentioned below:

Person(String userId, Instant requestingTime)

Similarly for Child class:

Child(Instant beginningDate, Instant endingDate, Collection fields)


Now as your program is throwing exception that

Parent() is undefined in parent class.

Please annotate your class with :

@NoArgsConstructor

This will generate required default constructor.



来源:https://stackoverflow.com/questions/60322188/how-to-use-lombok-superbuilder-on-abstract-classes-with-final-fields

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!