Lombok @builder in a class that extends another class

I have two Child extends Parent classes. I need to put the @Builder annotation on the classes so that I don't have to create my own constructor.

 package jerry;// Internal compiler error: java.lang.NullPointerException import lombok.AllArgsConstructor; import lombok.Builder; @AllArgsConstructor( onConstructor=@ __(@Builder)) public class Child extends Parent { //Multiple markers at this line // - Implicit super constructor Parent() is undefined. Must explicitly invoke another constructor // - overrides java.lang.Object.toString private String a; private int b; private boolean c; } @Builder public class Parent { private double d; private float e; } 

I need to create a child instance so that

 Child child = Child.builder().a("aVal").b(1000).c(true).d(10.1).e(20.0F).build(); 

But so far I am getting the errors mentioned in this code comment. Can someone point me in the right direction how to achieve this with a Lombok or any other similar library?

Sub-question

Why compilation @AllArgsConstructor( onConstructor=@ __(@Autowired)) , but @AllArgsConstructor( onConstructor=@ __(@Builder)) does not work?

+28
source share
3 answers

See https://blog.codecentric.de/en/2016/05/reducing-boilerplate-code-project-lombok/ (@Builder part and inheritance)

Adjusted for your classes

 @AllArgsConstructor public class Parent { private double d; private float e; } public class Child extends Parent { private String a; private int b; private boolean c; @Builder public Child(String a, int b, boolean c, double d, float e) { super(d, e); this.a = a; this.b = b; this.c = c; } } 

Using this setting

 Child child = Child.builder().a("aVal").b(1000).c(true).d(10.1).e(20.0F).build(); 

works correctly

+30
source

Starting with version 1.18.2, the hombard includes a new experiment @SuperBuilder . It supports fields from superclasses (also abstract). With it, the solution is so simple:

 @SuperBuilder public class Child extends Parent { private String a; private int b; private boolean c; } @SuperBuilder public class Parent { private double d; private float e; } Child instance = Child.builder().b(7).e(6.3).build(); 

Update 2019-10-09: if you use IntelliJ, to use @SuperBuilder you need at least version 0.27 of the IntelliJ Lombok plugin.

PS: @AllArgsConstructor( onConstructor=@ __(@Builder)) does not work, because @Builder is an annotation processing annotation that lombok converts to code at compile time. Creating and subsequently converting a new lombok annotation will require several iterations of annotation processing, and lombok does not support this. @Autowired , by contrast, is the usual Java annotation available at runtime.

+23
source

I have a similar but slightly different use case. In my case, I have a chain of abstract superclasses that build and execute queries. Different queries have common parameters, but not every query supports all parameters. Builders for specific queries should only provide methods for setting the supported parameters for a given query.

I started working with a constructor-based implementation of the constructor, but this led to too much code template, especially if you have many fields to configure. Now I have come up with the following solutions that look a lot cleaner for me.

Basically, specific subclasses define the actual fields that Builder must support, and the Getter annotation overrides the corresponding methods in the superclass. Getters in abstract superclasses can even be defined as abstract to require specific implementations to define these fields.

 public abstract class AbstractSuperClass1 { protected String getParamA() { return "defaultValueA"; } public final void doSomething() { System.out.println(getParamA()); doSomeThingElse(); } protected abstract void doSomeThingElse(); } 

 public abstract class AbstractSuperClass2 extends AbstractSuperClass1 { protected String getParamB() { return "defaultValueB"; } protected void doSomeThingElse() { System.out.println(getParamB()); } } 

 import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @Getter(AccessLevel.PROTECTED) @Builder public class ConcreteClass1 extends AbstractSuperClass2 { private final String paramA; // Not supported by this implementation: private final String paramB; public static void main(String[] args) { ConcreteClass1.builder() .paramA("NonDefaultValueA") .build().doSomething(); } } 

 import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @Getter(AccessLevel.PROTECTED) @Builder public class ConcreteClass2 extends AbstractSuperClass2 { private final String paramA; private final String paramB; public static void main(String[] args) { ConcreteClass2.builder() .paramA("NonDefaultValueA").paramB("NonDefaultValueB") .build().doSomething(); } } 
+1
source

Source: https://habr.com/ru/post/1269562/


All Articles