@builder注解_lombok之@Builder编译代码详解

结论

结论先行,阅读止步于此也可。
  1. @Builder无法直接使用字段默认值
  2. 需要在字段上使用@Default,才可以使用字段默认值
  3. @Builder会自动生成一个全参的构造函数

证明结论1 & 结论3

前提

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

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

通过观察编译之后的代码,通过Student$StudentBuilder.class我们可以知道@Builder注解生成了一个StudentBulder的静态内部类。

v2-54fba8cb8878817c487fd0be5b666b5e_b.jpg

将Student.class与Student$StudentBuilder.class反编译之后代码如下:

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

此时我们执行如下代码:

Student student = Student.builder().build();

此时studentstuStatus字段并不是你所期望的1,而是0。原因我们通过上述Student$StudentBuilder代码可以看出来:执行build()方法的时候使用的静态内部类的stuStatus,此时该字段为0。所以最终的studentstuStatus字段值为0。

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

证明结论2

Builder.java中可以发现, @Builder内部还有几个注解,此时我们需要使用的就是 @Default注解

前提

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

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

将Student.class与Student$StudentBuilder.class反编译之后代码如下:

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注解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值