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註解。

相關文章
相關標籤/搜索