使用Lombok @Builder後代碼詳解

前提

咱們有一個學生類:java

@Builder
public class Student {
  // 該字段有一個默認值;
  private int status = 1;
}

public class Test {
  @Test
  public void testBuilder() {
    // 生成的student對象並無使用status的默認值
    Student student = Student.builder().build();
  }
}

爲何@Builder沒有使用到默認值?

使用@Builder以後會生成一個靜態內部類StudentBuilder,編譯以後咱們能夠看到一共存在2個class文件。函數

clipboard.png

將Student.class與StudentBuilder.class反編譯以後的diamante以下ui

public class Student {
   private int status = 1;
   
   // 注意:此處lombok生成了一個全參的構造函數
   Student(int status) {
      this.status = status;
   }
   public static StudentBuilder builder() {
      return new StudentBuilder();
   }
}

public class Student$StudentBuilder {
   private int status;
   public Student$StudentBuilder status(int status) {
      this.status = status;
      return this;
   }
   public Student build() {
      return new Student(this.status);
   }
   public String toString() {
      return "Student.StudentBuilder(status=" + this.status + ")";
   }
}

在StudentBuilder代碼的build()方法中能夠看出來,生成Student對象時的status字段值是StudentBuilder中的status字段值。因此若是不經過status(int status)方法顯式的設置status字段的話,最終生成的對象中的status值是java中int的默認值0,而不是在Student類中規定的默認值1this

如何使默認值生效?

使用@Builder下面的@Default註解。spa

@Builder
public class Student {
  @Default
  private int status = 1;
}

編譯以後,將Student.class與StudentBuilder.class編譯以後的代碼以下:code

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

public class Student$StudentBuilder {
   private boolean status$set;
   private int status;
   public Student$StudentBuilder status(int status) {
      this.status = status;
      this.status$set = true;
      return this;
   }
   public Student build() {
      int status = this.status;
     // 會判斷stuStatus是否被顯式的set,若是沒有被set,則使用默認值。
      if(!this.status$set) {
         // 獲取Student類中status的默認值1
         status = Student.access$000();
      }
      return new Student(status);
   }
   public String toString() {
      return "Student.StudentBuilder(status=" + this.status + ")";
   }
}

在上文中能夠看到Student類中有一個access$000()的方法,用來返回status字段的默認值1;而後再看StudentBuilder類,在build()方法的時候會判斷是否顯式的給status字段賦值,若是沒有賦值則將status字段設置成默認值。對象

總結

  1. 若是想讓類中的字段默認值生效,須要使用@Default註解
  2. @Builder會生成一個全參的構造函數
相關文章
相關標籤/搜索