Lombok @Builder 用于具有强制字段的多级继承中的类

Posted

技术标签:

【中文标题】Lombok @Builder 用于具有强制字段的多级继承中的类【英文标题】:Lombok @Builder for a class in multiple level of inheritance with mandatory fields 【发布时间】:2021-11-21 17:40:38 【问题描述】:

我想在更深层次的继承中为类实现 Builder 模式,其中一些字段是必需的(消息、原因)和一些可选的(myOptField1、myOptField2...),使用 Lombok @Builder 并假设父类不能更改。所以我已经像这样实现了我自己的 builder():

@Builder(toBuilder = true)
@Getter
public class MyException extends Exception 

    private int    myOptField1;
    private String myOptField2;

    public static MyExceptionBuilder builder(String message, Throwable cause) 
        return new MyException(message, cause).toBuilder();
    

    public MyException(String message, Throwable cause) 
        super(message, cause);
    

那么这个类的使用可以是这样的:

MyException
    .builder("Mandatory message", new SpecificException("specificCause"))
    .myOptField2("value")
    .build();

在 IntelliJ Idea 中,一切似乎都很好,但出现编译错误:

java: constructor MyException in class com.myproject.MyException cannot be applied to given types;
required: java.lang.String,java.lang.Throwable
found: int,java.lang.String
reason: actual and formal argument lists differ in length

所以编译器只能看到 Lombok @Builder (=@AllArgsConstructor) 生成的构造函数,而看不到我的带有参数 java.lang.String,java.lang.Throwable 的构造函数。有没有更好的方法来解决这个问题?

【问题讨论】:

您可以尝试将@Builder 注释添加到您的构建器方法而不是类本身吗? 【参考方案1】:

我唯一想到的就是覆盖build() &toBuilder() 方法。 Lombok 根据不适合您的情况的字段生成自己的构造函数,而且 Lombok 对继承类中的字段一无所知。

在我看来,实现自己的 Builder 而不是破解 Lombok 解决方案更容易。


@Builder(toBuilder = true)
@Getter
public class MyException extends Exception 

    private int    myOptField1;
    private String myOptField2;

    public static MyExceptionBuilder builder(String message, Throwable cause) 
        return new MyException(message, cause).toBuilder();
    

    public MyException(String message, Throwable cause) 
        super(message, cause);
    

    MyExceptionBuilder toBuilder() 
        ....
    

    public static class MyExceptionBuilder 

        public MyException build() 
           ....
        
    

【讨论】:

【参考方案2】:

构建器模式的要点是不变性,因此您的可选值应该是最终的。您可以像这样将@Builder 放入构造函数中:

@Getter
static class MyException extends Exception 

    private final int    myOptField1;
    private final String myOptField2;

    @Builder
    public MyException(String message, Throwable cause, int myOptField1, String myOptField2) 
        super(message, cause);
        this.myOptField1 = myOptField1;
        this.myOptField2 = myOptField2;
    



MyException.builder().cause(new Exception()).message("").myOptField1(1).myOptField2("").build();

但不能保证强制值。如果它对您很重要,您可以制作自己的构建器。在 IntelliJ 中,转到 Refactor -> Delombok -> 选择 @Builder。您可以从@Builder 中看到生成的代码并自行修改。

【讨论】:

以上是关于Lombok @Builder 用于具有强制字段的多级继承中的类的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Lombok builder 中排除财产?

lombok中的@Builder.Default注解

Lombok中的@Builder注解的使用

Lombok同时使⽤@Data和@Builder 的坑

lombok的@builder 不能新建DO对象 Lombok存在的一些问题

@Builder lombok注解