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:

  1. @SuperBuilder@BuilderDo not mix parent and child classes
  2. @SuperBuilderIt must be used in all parent and child classes.