简体   繁体   中英

Lombok return custom build object in builder

I've a class which I don't have the ability to modify but would like to have a builder for it. I'm using Lombok.

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class SampleClass {
    private String a;
    private String b;
}

To have a builder for this, I create a BuilderClass:

@Builder
public class SampleClassBuilder {
    private String x;
    private String y;

    public SampleClass build() {
        SampleClass sampleClass = new SampleClass();
        sampleClass.setA(x + "testX");
        sampleClass.setB(y + "textY");
        return sampleClass;
    }
}

To use it, I will need to do:

SampleClass sampleClass = SampleClassBuilder.builder().x("x -- ").y("y---").build().build();

Is there a way to override build method to return SampleClass to avoid doing build.build?

I do not think that Lombok can do this: return another object from Builder. It even cannot call super in the builder.

Probably you could define your own build not using Lombok:

public class SampleBuilder {
    private String x;
    private String y;

    public static SampleBuilder builder() {
        return new SampleBuilder();
    }

    private SampleBuilder() {
    }

    public SampleBuilder x(String x) {
        this.x = x;
        return this;
    }

    public SampleBuilder y(String y) {
        this.y = y;
        return this;
    }

    public SampleClass build() {
        SampleClass sampleClass = new SampleClass();
        sampleClass.setA(x + "testX");
        sampleClass.setB(y + "textY");
        return sampleClass;
    }
}

And in your client code, you can see Lombok's like usage of builder:

SampleClass obj = SampleBuilder.builder().x("x").y("y").build();

If you just need to have custom builder's setters (like .x(...) .y(...) but not custom .build() ), you can just add SampleClassBuilder as static inner class to override some Lombok setter methods.

@Builder // <--- Put @Builder at the SampleClass itself, not at Builder class
@ToString
class SampleClass { // Lombok will internally create SampleClassBuilder

    private String x;
    private String y;
    private int a,b,c;
    private String z;

    public static class SampleClassBuilder{ // Need to name like this to override Lombok class
        public SampleClassBuilder x(String x){
            this.x = x + "testX"; // Lombok will also create `this.x` for this builder class (also y,a,b,c,z)
            return this;
        }
        public SampleClassBuilder y(String y){
            this.y = y + "testY";
            return this;
        }
        public SampleClassBuilder z(String z){
            this.z = this.x + this.y; // *`.z()` must be called lastly if refer to other fields
            return this;
        }
    }

To use it, you can simply do this:

SampleClass sample = SampleClass.builder().x("One").z(null).y("Two").a(1).b(2).c(3).build();
System.out.println(sample); // SampleClass(x=OnetestX, y=TwotestY, a=1, b=2, c=3, z=OnetestXnull)

*Please note that using this pattern, .z(...) needs to be called after others; otherwise, the value will be wrong as z ="OnetestX null " because y is null at that time.

To overcome this issue:

  • You can append this.z(null) into method x() and y()
  • Or, use another pattern here: https://stackoverflow.com/a/65773183/2710335 to avoid putting this.z(null) everywhere (Eg. this.z = this.x + this.y + this.a + this.b + this.c + ...; ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM