【问题标题】:Lombok's builder with mandatory parameters带有强制参数的龙目岛构建器
【发布时间】:2021-07-31 23:08:07
【问题描述】:

如果我将@Builder 添加到一个类中。生成器方法已创建。

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 检查,这将在创建对象时强制为名称提供值。但它是运行时检查。它不会强迫我在创建对象时为 name 提供值。

lombok 是否提供任何其他技术来实现以下目标:

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

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

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

【问题讨论】:

    标签: java builder lombok


    【解决方案1】:

    你不能用 lombok 来做,见the explanation from the library authors。但是,自己构建这个构建器有那么复杂吗?

    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);
        }
    

    【讨论】:

      【解决方案2】:

      尝试将构建器设为私有。

      你查看这条评论Required arguments with a Lombok @Builder

      我很确定你再读一遍就会发现。

      附:如果你有一个只有两个字段的类,最好直接使用构造函数。

      【讨论】:

      • 感谢您的回复。我检查了线程,我发现很少有事情没有回答。将构建器设为私有解决了其中一个问题。但我的另一个担忧是 name() 方法是可见的,可以像下面这样使用它:Person.builder("Name").surname("Surname").name("").build(); 在这种情况下,builder() 中提供的值将被更改。
      • @rohit 我相信您必须编写自己的构建器,而不是为您的特定情况使用 Lombok,因为看起来,字段仍然是公开的。
      【解决方案3】:

      最佳实践:

      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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-03-17
        • 1970-01-01
        • 1970-01-01
        • 2023-04-10
        • 2021-10-02
        • 2021-03-27
        • 2015-10-18
        相关资源
        最近更新 更多