lombok中@Builder注解注意事项:没法直接使用字段默认值

结论

结论先行,阅读止步于此也可。java

  1. @Builder没法直接使用字段默认值
  2. 须要在字段上使用@Default,才可使用字段默认值
  3. @Builder会自动生成一个全参的构造函数

证实结论1 & 结论3

前提

咱们有一个学生类(为了方便,咱们只使用1个字段。该字段带默认值)函数

@Builder
public class Student {
  private int stuStatus = 1;
}
复制代码

经过观察编译以后的代码,经过Student$StudentBuilder.class咱们能够知道@Builder注解生成了一个StudentBuilder的静态内部类。ui

将Student.class与Student$StudentBuilder.class反编译以后代码以下:this

public class Student {
   private int stuStatus = 1;
   // 注意此处:@Builder已经生成了一个全参构造函数。因此不能直接使用new Student()。若是想使用那么须要使用另外一个注解:@NoArgsConstructor
   Student(int stuStatus) {
      this.stuStatus = stuStatus;
   }
   public static StudentBuilder builder() {
      return new StudentBuilder();
   }
}

public class Student$StudentBuilder {
   private int stuStatus;
   public Student$StudentBuilder stuStatus(int stuStatus) {
      this.stuStatus = stuStatus;
      return this;
   }
   public Student build() {
      return new Student(this.stuStatus);
   }
   public String toString() {
      return "Student.StudentBuilder(stuStatus=" + this.stuStatus + ")";
   }
}
复制代码

此时咱们执行以下代码:spa

Student student = Student.builder().build();
复制代码

此时studentstuStatus字段并非你所指望的1,而是0。缘由咱们经过上述Student$StudentBuilder代码能够看出来:执行build()方法的时候使用的静态内部类的stuStatus,此时该字段为0。因此最终的studentstuStatus字段值为0。code

Q:如何才能使用stuStatus的默认值呢?
A: 为使用默认值的字段使用@Default注解(详细说明见下文)。cdn

证实结论2

Builder.java中能够发现,@Builder内部还有几个注解,此时咱们须要使用的就是@Default注解blog

前提

咱们有一个学生类(此时使用@Default注解)string

@Builder
public class Student {
  @Default
  private int stuStatus = 1;
}
复制代码

将Student.class与Student$StudentBuilder.class反编译以后代码以下:it

public class Student {
   private int stuStatus;
   // 返回stuStatus的默认值1
   private static int $default$stuStatus() {
      return 1;
   }
   Student(int stuStatus) {
      this.stuStatus = stuStatus;
   }
   public static StudentBuilder builder() {
      return new StudentBuilder();
   }
   // $FF: synthetic method
   static int access$000() {
      return $default$stuStatus();
   }
}

public class Student$StudentBuilder {
   private boolean stuStatus$set;
   private int stuStatus;
   public Student$StudentBuilder stuStatus(int stuStatus) {
      this.stuStatus = stuStatus;
      this.stuStatus$set = true;
      return this;
   }
   public Student build() {
      int stuStatus = this.stuSstuStatustauts;
     // 会判断stuStatus是否被显式的set,若是没有被set,则使用默认值。
      if(!this.stuStatus$set) {
         stuStatus = Student.access$000();
      }
      return new Student(stuStatus);
   }
   public String toString() {
      return "Student.StudentBuilder(stuStatus=" + this.stuStatus + ")";
   }
}
复制代码

此时咱们执行以下代码:

Student student = Student.builder().build();
复制代码

此时studentstuStatus字段就是你所指望的1。缘由:咱们经过上述Student$StudentBuilder代码能够看出来:执行build()方法的时候会判断程序是否设置了stuStatus字段,若是没有设置(stuStatus$set是false)则调用Student.access$000()(该方法便是获取字段默认值)为stuStatus赋值。

写在后面

经过分析,明白了lombok为什么不能直接使用字段默认值了。可是至于lombok为什么这么作就不了解了。我给字段设置默认值的缘由就是想不为该字段赋值的时候,字段能直接使用默认值,可是lombok却直接忽略了默认值,而是额外须要@Default注解。

相关文章
相关标签/搜索