覆盖 lombok 构建器并更改值类型

Posted

技术标签:

【中文标题】覆盖 lombok 构建器并更改值类型【英文标题】:Override lombok builder and change value type 【发布时间】:2022-01-23 08:01:16 【问题描述】:

我有以下带有 Lombok @Builder 的类,其中我覆盖了一个构建器方法以将输入字符串列表转换为枚举列表(字段 barList):

(其他字段number我还是用默认方式)

import java.util.List;
import java.util.stream.Collectors;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder(toBuilder = true)
public class Foo 
    private List<BarEnum> barList;
    private int number;

    public static class FooBuilder 
        private List<BarEnum> barList;
       
        public FooBuilder barList(List<String> barStringList) 
            this.barList = barStringList.stream()
                                        .map(barString -> BarEnum.valueOf(barString))
                                        .collect(Collectors.toList());
            return this;
        
    

编译时,我在上面的@Builder(toBuilder = true) 行收到此错误:

不兼容的类型:java.util.List 不能 转换为 java.util.List

我找不到任何可以覆盖默认构建器方法并更改值类型的答案。可以这样做吗?

【问题讨论】:

【参考方案1】:

首先我们运行 delombok 以更好地了解正在发生的事情,然后编译输出。

java -jar lombok.jar delombok -p Foo.java >Foo2.java
# Rename Foo2.java or make the `class Foo` declaration non-public
javac Foo2.java

得到我们:

Foo2.java:63: error: incompatible types: List<BarEnum> cannot be converted to List<String>
        return new Foo.FooBuilder().barList(this.barList).number(this.number);
                             ^

然后答案很明确:Lombok 需要构建器 barList 方法的barList(List&lt;BarEnum&gt;) 变体存在。通过自己编写,lombok 不会生成自己的版本。

Lombok 核心开发人员在此发言:我们没有,因为很难确定是否存在签名冲突。因此,我们注意到一个方法与我们想要生成的东西具有相同的名称和相同的参数计数,我们不做任何进一步的分析:这是一个“匹配”,意味着 lombok 不再生成这个方法,假设你已经接管了它的责任。这是一个很好的例子:除了显式的barList(List&lt;String&gt;) 方法之外,不能有barList(List&lt;BarEnum&gt;) 方法,因为你不能有两个仅在参数的泛型部分不同的方法! (尝试一下 - 不会编译)。

因此,您在这里的做法根本站不住脚。修复相当简单 - 使自定义方法类似于:

public FooBuilder barStringList(List<String> barStringList)  .. 

即给它另一个名字。现在lombok也会生成barList(List&lt;BarEnum&gt;),一切都会好起来的。

如果您希望 barlist(List&lt;BarEnum&gt;) 变体不存在,那么不要,但您必须手写其中的 toBuilder() 部分:此时,lombok 不再可能自动知道如何如果您开始有效地删除作为“设置器”所需的方法以使其工作,则不再将实例变成预填充的构建器。

免责声明:我是核心 lombok 开发人员。

【讨论】:

感谢您的详细回复。如果我已经提供了barList(List&lt;String&gt;) 并且像你说的那样,Lombok 就不会生成barList(List&lt;BarEnum&gt;) -> 那么这很好,对吧?我不需要该字段的默认方法。对不起,如果我误解了什么。 不,barList(List&lt;BarEnum&gt;) 方法是toBuilder 部分所必需的。没有问题,它必须在那里才能使 toBuilder 工作。要么 [A] 将其放回原处(通过将您的 barList 方法命名为其他名称,或者 [B] 编写您自己的 toBuilder impl。

以上是关于覆盖 lombok 构建器并更改值类型的主要内容,如果未能解决你的问题,请参考以下文章

OroPlatform:覆盖核心实体表单构建器

Laravel 8,创建一个查询构建器并逐步向其中添加更多查询,如何逐步回滚?

三个 js - 克隆着色器并更改统一值

带有杰克逊 JsonProperty 的 Lombok 构建器模式

NonNull Lombok 构建器属性的 FindBugs 检测器

如何使用 Laravel 模式构建器更改列类型?