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

Override lombok builder and change value type

我有下面的 class 和 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) 行收到此错误:

incompatible types: java.util.List<com.mypackage.BarEnum> cannot be converted to java.util.List<java.lang.String>

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

首先我们 运行 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 需要 builder barList 方法的 barList(List<BarEnum>) 变体才能存在。通过自己编写,lombok 不会生成自己的版本。

Lombok 核心开发者在这里发言:我们没有,因为很难确定是否存在签名冲突。因此,我们注意到一个方法与我们想要生成的东西同名并且具有相同的参数计数,我们不做任何进一步的分析:那是一个 'match' 并且意味着 lombok 不再生成这个方法,假设你已经接管了它的责任。这是一个非常好的示例:除了您的显式 barList(List<String>) 方法之外,不能有 barList(List<BarEnum>) 方法,因为您不能有 2 个仅在参数的泛型部分不同的方法! (试一试 - 不会编译)。

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

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

即给它另一个名字。现在lombok也会生成barList(List<BarEnum>),一切都会好的

如果您希望 barlist(List<BarEnum>) 变体不存在,那就不要,但是您必须手写其中的 toBuilder() 部分:在这一点上它不再可能lombok 自动知道如何将一个实例变成一个预填充的构建器,如果你开始只是有效地删除 'setters' 使它工作所需的方法。

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