Lombok allows us to provide a powerful tool for our productivity, with simple annotations to simplify code, eliminate verbosity, and improve development efficiency. One of my favorite annotations to use is @Builder, which makes it easy to use the constructor pattern. This article documents how to use @Builder in subclasses to avoid a common pitfall.
A, problem,
For the following two classes, one parent and one subclass. Both classes want to use the @Builder annotation to construct an object using the constructor pattern.
@Getter
@ToString
public class Parent {
private long id;
private String name;
@Builder
@Getter
@ToString
static class Child extends Parent{
privateString value; }}Copy the code
When we try to compile the above code, we get an error that says something like this.
The constructor Parent in class < package path >.Parent cannot be applied to a given type;
The reason for this is that Lombok does not consider the fields of the parent class, but only the fields of the current child class.
Second, solutions
There are several solutions, the simplest of which is to include the fields of the parent class in the constructor of the subclass and use @Builder annotations on the constructor.
@Getter
@AllArgsConstructor
@ToString
public class Parent {
private long id;
private String name;
@Getter
@ToString
static class Child extends Parent{
private String value;
@Builder
public Child(long id,String name,String value){
super(id,name);
this.value = value; }}}Copy the code
This solves the above problem, but if we want to annotate the parent class with @Builder, the code below looks like this.
@Getter
@AllArgsConstructor
@ToString
@Builder
public class Parent {... }Copy the code
Another error is reported when compiling.
< package path >.child () cannot override Builder () in < package path >.parent
The subclass attempts to declare a Builder with the same name as the parent class. We can solve this problem by replacing a constructor name for the subclass, as shown in the code below, with a custom name for the Builder of the subclass.
@Builder(builderMethodName = "childBuilder")
public Child(long id,String name,String value){
super(id,name);
this.value = value;
}
Copy the code
What if I inherit from a deeper class, like another class that inherits from Child and also wants to use Builder? The simplest way to think about it is to rewrite the constructor of an inherited class, as above, to support all fields of the parent class.
What else is easy and quick to do? The answer is that Lombok itself provides a proven solution.
Better solutions
Lombok version 1.18 introduced the @SuperBuilder annotation, which solves the problem we encountered above by annotating both parent and subclass classes.
@Getter
@AllArgsConstructor
@ToString
@SuperBuilder
public class Parent {
private long id;
private String name;
@Getter
@ToString
@SuperBuilder
static class Child extends Parent{
private String value;
}
@Getter
@ToString
@SuperBuilder
static class ChildSChild extends Child{
privateString personality; }}Copy the code
Two points to note:
@SuperBuilder
和@Builder
Do not mix parent and child classes@SuperBuilder
It must be used in all parent and child classes.