Lombok cannot build parent class properties using @Builder

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.
insert image description here
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.
insert image description here
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

Guess you like

Origin blog.csdn.net/u014212540/article/details/129424508
Recommended