如何在Lombok的.build()阶段自动填充BookSummary的summary字段?
问题:用Lombok Builder自动填充字段,同时兼容直接字段访问的优雅实现
我需要在调用.build()方法时,自动给BookSummary类的summary字段赋值,目前是通过自定义构造器实现的,但想找更简洁优雅的写法。
关键限制:部分接收该对象的API会直接读取字段而非访问器方法,比如Gson序列化时,会直接读取summary字段的默认值,不会走重写后的getSummary()方法,所以靠重写get方法这条路走不通。
现有代码结构
父类 Book
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @Data @AllArgsConstructor @NoArgsConstructor @SuperBuilder public class Book { protected String title; protected String author; protected String description; }
当前实现的 BookSummary(自定义构造器方式)
import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.SuperBuilder; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @AllArgsConstructor @NoArgsConstructor @SuperBuilder public class BookSummary extends Book { public String summary; public BookSummary(BookSummaryBuilder<?, ?> b) { super(b); this.summary = getTitle() + getAuthor() + getDescription(); } }
无效方案示例(重写getSummary()+@Builder.Default)
我试过用@Builder.Default给summary设默认值,同时重写getSummary()方法动态生成内容,但Gson序列化时会直接读取字段值,导致结果完全不符合预期:
public class BookSummary extends Book { @Builder.Default public String summary = "xxxxxxxxxxxxxxx"; public String getSummary() { return getTitle() + getAuthor() + getDescription(); } } // 测试代码 BookSummary bookSummary = BookSummary.builder() .title("Java forever") .author("John John") .description("bla-bla-bla-bla") .build(); String json = new GsonBuilder().create().toJson(bookSummary);
序列化后的JSON结果:
{ "summary":"xxxxxxxxxxxxxxx", "title":"Java forever", "author":"John John", "description":"bla-bla-bla-bla" }
优雅解决方案推荐
方案:自定义Builder的build()方法
利用Lombok @SuperBuilder生成的Builder类,重写它的build()方法,在构建实例后直接给summary字段赋值,既简洁又能保证字段被正确填充:
import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.SuperBuilder; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @AllArgsConstructor @NoArgsConstructor @SuperBuilder public class BookSummary extends Book { public String summary; public static class BookSummaryBuilder<C extends BookSummary, B extends BookSummaryBuilder<C, B>> extends BookBuilder<C, B> { @Override public C build() { C instance = super.build(); // 直接给字段赋值,兼容所有读取字段的场景 instance.summary = instance.getTitle() + instance.getAuthor() + instance.getDescription(); return instance; } } }
验证效果
用这个方案构建对象后,Gson序列化的结果会是:
{ "summary":"Java foreverJohn Johnbla-bla-bla-bla", "title":"Java forever", "author":"John John", "description":"bla-bla-bla-bla" }
完全符合预期,而且代码比自定义构造器更简洁,也更贴合Lombok的设计思路。
内容的提问来源于stack exchange,提问作者VeryNiceArgumentException
相关产品推荐
相关产品推荐

