Article directory
Problem Description
The entity class uses Lombok's @Builder to implement the Builder pattern, but if extend inheritance is used, the subclass cannot use the Builder to build the parent class attribute value
solution
Add @NoArgsConstructor and @AllArgsConstructor annotations to the parent class to add no-argument and full-argument constructors [Note: The parent class attribute cannot be set to private, otherwise it will still be inaccessible, and the parent class is not allowed to have @Builder annotations, otherwise it will conflict with the subclass]
Subclasses add @NoArgsConstructor to add no-argument constructors, and customize a full-argument constructor (including parent class attributes)
Example of use
father:
package com.baijia.uqun.individual.management.facade;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* @Author C.W
* @Date 2020/6/15 5:25 下午
* @Description 父类
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Father {
/**
* 父类名称
*/
public String fatherName;
}
Subclass:
package com.baijia.uqun.individual.management.facade;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* @Author C.W
* @Date 2020/6/15 5:26 下午
* @Description 子类
*/
@Setter
@Getter
@NoArgsConstructor
public class Child extends Father {
/**
* 子类名称
*/
private String childName;
/**
* 用于解决Lombok的Builder无法Build父类属性问题
*
* @param fatherName
* @param childName
*/
@Builder(toBuilder = true)
public Child(String fatherName, String childName) {
super(fatherName);
this.childName = childName;
}
}
use:
package com.baijia.uqun.individual.management.facade;
/**
* @Author C.W
* @Date 2020/6/15 5:28 下午
* @Description 测试代码
*/
public class Test {
public static void main(String[] args) {
// 创建一个子类
Child child = Child.builder()
.fatherName("父类名称")
.childName("子类名称")
.build();
System.out.println(String.format("父类名称:%s,子类名称:%s", child.getFatherName(), child.getChildName()));
}
}
lombok @Builder annotation and build parent class attribute problem
1 Introduction
Through the @Builder annotation, lombok can conveniently practice the builder mode.
2. use
1) Create a base class User
import lombok.*;
/**
* @author Saint
*/
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
private Long id;
private String name;
}
2) Create a subclass UserExt
import lombok.*;
/**
* @author Saint
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class UserExt extends User{
private String address;
private Integer age;
}
3) Use Builder to create the parent class and subclass respectively
// 父类
User user = User.builder().id(1L).name("saint").build();
// 子类
UserExt userExt = UserExt.builder().address("南京").age(18).build();
3. What does the @Builder annotation do to the class?
Decompiled UserExt.class:
public class UserExt extends User {
private String address;
private Integer age;
public static UserExt.UserExtBuilder builder() {
return new UserExt.UserExtBuilder();
}
public String getAddress() {
return this.address;
}
public Integer getAge() {
return this.age;
}
public void setAddress(final String address) {
this.address = address;
}
public void setAge(final Integer age) {
this.age = age;
}
public UserExt() {
}
public UserExt(final String address, final Integer age) {
this.address = address;
this.age = age;
}
public String toString() {
return "UserExt(address=" + this.getAddress() + ", age=" + this.getAge() + ")";
}
public static class UserExtBuilder {
private String address;
private Integer age;
UserExtBuilder() {
}
public UserExt.UserExtBuilder address(final String address) {
this.address = address;
return this;
}
public UserExt.UserExtBuilder age(final Integer age) {
this.age = age;
return this;
}
public UserExt build() {
return new UserExt(this.address, this.age);
}
public String toString() {
return "UserExt.UserExtBuilder(address=" + this.address + ", age=" + this.age + ")";
}
}
}
After the annotation is compiled, a static inner class named UserExt.UserExtBuilder is added to the UserExt class. This static class has the same properties as the UserExt class, and it implements some additional methods:
1. The attribute method of address and age
In fact, these methods are very similar to setAttribute, except that the instance itself is additionally returned, which makes it possible to use a writing method similar to chain calls.
2. build method
This method calls the full-parameter constructor of the UserExt class to generate a UserExt instance.
The UserExt class still implements the builder method, which generates an empty UserExt.UserExtBuilder instance.
4. Advantages and disadvantages
Advantages:
The writing method is more elegant and does not require too many set methods to set attributes.
Disadvantage:
Before generating the UserExt instance, a UserExt.UserExtBuilder instance is created, which occupies additional memory. And Java is passed by value, we can directly modify the reference object without creating a new object and assigning a value; and the Builder.build() method will generate a new instance every time it is called.
5. Problem: The @Builder annotation cannot build parent class properties
From the decompiled UserExt class, it can be seen that UserExtBuilder does not have the properties inherited from the parent class User: filling methods for id and name.
solution:
Use @SuperBuilder in both subclasses and parent classes, remove @Builder. But it can also be seen from the imported package that the @SuperBuilder annotation is experimental. I don't know if there are any potential risks, so use with caution.
From the decompiled User and UserExt classes:
public abstract static class UserBuilder<C extends User, B extends User.UserBuilder<C, B>>
public abstract static class UserExtBuilder<C extends UserExt, B extends UserExt.UserExtBuilder<C, B>> extends UserBuilder<C, B>
lombok made an inheritance relationship between UserBuilder and UserExtBuilder