具有强制参数的 Lombok 构建器

Lombok's builder with mandatory parameters

如果我将@Builder 添加到 class。生成器方法已创建。

Person.builder().name("john").surname("Smith").build();

我有一个要求,其中某个特定字段是必填项。在这种情况下,名称字段是强制性的。理想情况下,我想这样声明。

Person.builder("john").surname("Smith").build();

在谷歌搜索时,我发现了很多替代方法,例如覆盖构建器实现,如下所示:

@Builder
public class Person {

    private String name;
    private String surname;

    public static PersonBuilder builder(String name) {
        return new PersonBuilder().name(name);
    }
}

然后像下面这样使用它:

Person p = Person.builder("Name").surname("Surname").build();

上述方法的问题是它仍然提供如下的 name() 和 PersonBuilder() 方法,我不想要这样的方法:

Person p = Person.builder("Name").surname("Surname").name("").build();
Person p = new Person.PersonBuilder().build;

另一种方法是在名称上添加@lombok.nonnull 检查,这将在创建对象时强制为名称提供值。但这是一个运行时检查。它不会强迫我在创建对象时为名称提供值。

lombok 是否提供了任何额外的技术来实现以下目标:

 Person p = Person.builder("Name").surname("Surname").build();

注意:不应公开 builder() 和 name()。创建 Person 对象的唯一方法应该是在上面或下面:

 Person p = Person.builder("Name").build();

你不能用 lombok 真正做到这一点,请参阅 the explanation from the library authors。但是自己动手做这个builder有那么复杂吗?

public static class PersonBuilder {

    private final String name;
    private String surname;

    PersonBuilder(String name) {
        this.name = name;
    }

    public PersonBuilder surname(String surname) {
        this.surname = surname;
        return this;
    }

    public Person build() {
        return new Person(name, surname);
    }
        
}

使用您已有的相同方法:

    public static PersonBuilder builder(String name) {
        return new PersonBuilder(name);
    }

尝试将生成器设为私有。

你看这条评论了吗

我很确定你再读一遍这个帖子就会知道了。

P.S。如果你有一个只有两个字段的 class 最好直接使用构造函数。

最佳实践:

import lombok.Builder;
import lombok.NonNull;

@Builder(builderMethodName = "privateBuilder")
public class Person {
    @NonNull
    private String name;
    private String surname;

    public static class PersonNameBuilder {
        public PersonBuilder name(String name) {
            return Person.privateBuilder().name(name);
        }
    }
    
    private static class PersonExtraBuilder extends PersonBuilder{
        @Deprecated
        @Override
        public PersonBuilder name(String name) {
            return this;
        }
    }

    public static PersonNameBuilder builder(String name) {
        return new PersonNameBuilder();
    }

    private static PersonExtraBuilder privateBuilder(){
        return new PersonExtraBuilder();
    }
}

用法:

PersonNameBuilder nameBuilder = Person.builder();
PersonBuilder builder = nameBuilder.name("John");
Person p1 = builder.surname("Smith").build();

// Or
Person p2 = Person.builder().name("John").surname("Smith").build();

// The last `.name("")` will not work, and it will be marked as Deprecated by IDE.
Person p3 = Person.builder().name("John").surname("Smith").name("").build();