lombok @Builer.Default 需要注意的坑

梦里梦外; 2022-04-16 01:58 378阅读 0赞

最近在开发过程中,想让实体类中的boolean字段默认为true,于是我在字段定义后赋值为true,同时该类上有@Builder注解,我希望在使用builder方式创建实例的时候该字段也能默认为true,查看资料后发现@Builder.Default注解很合适。实际运行代码之后,我发现一个无奈的问题,builder模式下默认值生效了,但是使用new得到的实例默认值为false。贴上测试代码,清晰些。

  1. import lombok.AllArgsConstructor;
  2. import lombok.Builder;
  3. import lombok.NoArgsConstructor;
  4. import lombok.ToString;
  5. public class testLombok {
  6. public static void main(String[] args) {
  7. People p1 = new People();
  8. System.out.println(p1); //People(old=false)
  9. People p2 = People.builder().build(); //People(old=true)
  10. System.out.println(p2);
  11. }
  12. }
  13. @Builder
  14. @ToString
  15. @NoArgsConstructor
  16. @AllArgsConstructor
  17. class People {
  18. @Builder.Default
  19. private boolean old = true;
  20. }

为什么会这样呢?心里一万头羊驼跑过…

我们来看反编译后的People代码

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. import java.beans.ConstructorProperties;
  6. class People {
  7. private boolean old;
  8. private static boolean $default$old() {
  9. return true;
  10. }
  11. public static People.PeopleBuilder builder() {
  12. return new People.PeopleBuilder();
  13. }
  14. public String toString() {
  15. return "People(old=" + this.old + ")";
  16. }
  17. public People() {
  18. }
  19. @ConstructorProperties({"old"})
  20. public People(boolean old) {
  21. this.old = old;
  22. }
  23. public static class PeopleBuilder {
  24. private boolean old$set;
  25. private boolean old;
  26. PeopleBuilder() {
  27. }
  28. public People.PeopleBuilder old(boolean old) {
  29. this.old = old;
  30. this.old$set = true;
  31. return this;
  32. }
  33. public People build() {
  34. return new People(this.old$set ? this.old : People.$default$old());
  35. }
  36. public String toString() {
  37. return "People.PeopleBuilder(old=" + this.old + ")";
  38. }
  39. }
  40. }

从最开始看起,代码中old字段没有赋初值,并且多了一个static方法$default$old,方法的返回值即为设置的默认值。接着往后看,在静态内部类PeopleBuilder 中的build方法中对old字段进行了判断,如果没有被设置值,那么就将$default$old方法中的默认值赋给People实例。现在终于明白之前的困惑,并且顺带了解了@Builder.Default的实现原理。

既然@Builder.Default没有办法解决问题,那么该怎么办呢?

可以换个思路,实例初始化的时候,boolean字段会被初始化为false,利用这个特性把字段名字改为notOld即可。代码如下

  1. public class People {
  2. private boolean notOld;
  3. }

发表评论

表情:
评论列表 (有 0 条评论,378人围观)

还没有评论,来说两句吧...

相关阅读