探究lombok-02-类继承

Java 8

org.springframework.boot 2.7.3

lombok 1.18.24

Eclipse Version: 2022-09 (4.25.0)

--ben发布于博客园

 

上一篇:探究lombok-01

https://www.cnblogs.com/luo630/p/16941897.html

注,本文测试结果的 LombokMain.java 的代码与上一篇相同。

 

0、序章

本文主要介绍类继承时使用lombok注解。涉及:ben发布于博客园

@Data、@Builder、@SuperBuilder

 

1、父子类都用@Data(可行)

孤使用频率最高的方式。ben发布于博客园

测试类:BaseDataVO、UserDataVO

// 1、BaseDataVO
import lombok.Data;

@Data
public class BaseDataVO {

	private Integer supId;
	private String supName;
	
}

// 2、UserDataVO
import java.util.Date;
import java.util.List;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Data
//@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class UserDataVO extends BaseDataVO {

	private Integer id;
	private String name;
	private List<String> tags;
	private Date createTime;
	
}

 

测试结果:和 前一篇 一直,多了几个成员方法

都用@Data的测试结果
 测试:class=class com.lib.webdemo.vo2.BaseDataVO
prtClasses: length=0
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo2.BaseDataVO, 参数数量:0, modifiers=1
----
prtFields: length=2
字段:supId, type=class java.lang.Integer, modifiers=2
字段:supName, type=class java.lang.String, modifiers=2
----
prtMethods: length=8
方法名称:equals, 参数数量:1, modifiers=1
方法名称:toString, 参数数量:0, modifiers=1
方法名称:hashCode, 参数数量:0, modifiers=1
方法名称:setSupId, 参数数量:1, modifiers=1
方法名称:setSupName, 参数数量:1, modifiers=1
方法名称:getSupId, 参数数量:0, modifiers=1
方法名称:getSupName, 参数数量:0, modifiers=1
方法名称:canEqual, 参数数量:1, modifiers=4


测试:class=class com.lib.webdemo.vo2.UserDataVO
prtClasses: length=0
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo2.UserDataVO, 参数数量:0, modifiers=1
----
prtFields: length=4
字段:id, type=class java.lang.Integer, modifiers=2
字段:name, type=class java.lang.String, modifiers=2
字段:tags, type=interface java.util.List, modifiers=2
字段:createTime, type=class java.util.Date, modifiers=2
----
prtMethods: length=12
方法名称:equals, 参数数量:1, modifiers=1
方法名称:toString, 参数数量:0, modifiers=1
方法名称:hashCode, 参数数量:0, modifiers=1
方法名称:getName, 参数数量:0, modifiers=1
方法名称:getId, 参数数量:0, modifiers=1
方法名称:setName, 参数数量:1, modifiers=1
方法名称:setId, 参数数量:1, modifiers=1
方法名称:setTags, 参数数量:1, modifiers=1
方法名称:setCreateTime, 参数数量:1, modifiers=1
方法名称:canEqual, 参数数量:1, modifiers=4
方法名称:getTags, 参数数量:0, modifiers=1
方法名称:getCreateTime, 参数数量:0, modifiers=1

 

创建新对象及打印:在测试类 LombokMain 中添加下面的函数

private static void testDataVo() {
    cs.accept("\n\n测试:testDataVo...");

    BaseDataVO base = new BaseDataVO();
    base.setSupId(999);
    base.setSupName("super999");
    cs.accept("BaseDataVO base=" + base);

    UserDataVO user = new UserDataVO();
    // 父
    user.setSupId(888);
    user.setSupName("super888");
    // 子
    user.setId(1);
    user.setName("sub1");
    user.setTags(new ArrayList<>());
    user.setCreateTime(new Date());
    cs.accept("UserDataVO user=" + user);
}

测试结果:

测试:testDataVo...
BaseDataVO base=BaseDataVO(supId=999, supName=super999)
UserDataVO user=UserDataVO(super=BaseDataVO(supId=888, supName=super888), id=1, name=sub1, tags=[], createTime=Fri Dec 02 19:21:12 CST 2022)

说明,UserDataVO 中的 super 为 父类的值,是因为 使用了注解 @ToString(callSuper = true) 才有的。ben发布于博客园

 

小结

常用方式。可行。要配合 @ToString(callSuper = true)  使用才能输出父类属性,或自己手写toString函数。

 

2、父子类都用@Builder(不可行)

此方式不可行

测试类:BaseBuilderVO、UserBuilderVO

// 1、BaseBuilderVO
import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class BaseBuilderVO {

	private Integer supId;
	private String supName;
	
}

// 2、UserBuilderVO
import java.util.Date;
import java.util.List;

import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Builder // 合理存在错误(1)
@ToString
public class UserBuilderVO extends BaseBuilderVO {

	private Integer id;
	private String name;
	private List<String> tags;
	private Date createTime;
	
}

错误(1):Eclipse提示如下

Implicit super constructor BaseBuilderVO() is undefined. Must explicitly invoke another constructor

BaseBuilderVO 没有默认构造函数 导致。ben发布于博客园

 

给 BaseBuilderVO 添加 @NoArgsConstructor 注解,此时,BaseBuilderVO  存在错误:

The constructor BaseBuilderVO(Integer, String) is undefined

再添加 @AllArgsConstructor 注解,BaseBuilderVO 未报错,但 UserBuilderVO 仍然报错:

UserBuilderVO 从错误 和之前一样。

这样看来,在 BaseBuilderVO 添加 @NoArgsConstructor 、 @AllArgsConstructor 无法解决问题(参考资料#2)。

进一步测试,在 UserBuilderVO 上添加 @NoArgsConstructor 、 @AllArgsConstructor 也解决不了报错。ben发布于博客园

 

参考资料#2 提到一种 手动创建构造函数的方式:试验未成功

从 @Builder 注解的源码来看,它可以用在 类型、成员方法、构造器上面:

@Target({TYPE, METHOD, CONSTRUCTOR})
@Retention(SOURCE)
public @interface Builder {
//...
}

还需进一步探索。TODO

 

小结

放弃使用 @Builder 实现 类继承。ben发布于博客园

 

3、使用@SuperBuilder(可行)

按照 参考资料#2 的介绍,这是一个  试验性质 的注解。

import lombok.experimental.SuperBuilder;

包名里面有一个 experimental

 

父类使用 @SuperBuilder

建立一个父类:BaseSuperBuilderVO

import lombok.experimental.SuperBuilder;

@SuperBuilder
@ToString
public class BaseSuperBuilderVO {

	private Integer supId;
	private String supName;
	
}

类检查结果:

测试:class=class com.lib.webdemo.vo2.BaseSuperBuilderVO
prtClasses: length=2
内部类: com.lib.webdemo.vo2.BaseSuperBuilderVO.BaseSuperBuilderVOBuilder, com.lib.webdemo.vo2.BaseSuperBuilderVO$BaseSuperBuilderVOBuilder, BaseSuperBuilderVOBuilder, com.lib.webdemo.vo2.BaseSuperBuilderVO$BaseSuperBuilderVOBuilder, modifiers=1033
内部类: com.lib.webdemo.vo2.BaseSuperBuilderVO.BaseSuperBuilderVOBuilderImpl, com.lib.webdemo.vo2.BaseSuperBuilderVO$BaseSuperBuilderVOBuilderImpl, BaseSuperBuilderVOBuilderImpl, com.lib.webdemo.vo2.BaseSuperBuilderVO$BaseSuperBuilderVOBuilderImpl, modifiers=26
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo2.BaseSuperBuilderVO, 参数数量:1, modifiers=4
----
prtFields: length=2
字段:supId, type=class java.lang.Integer, modifiers=2
字段:supName, type=class java.lang.String, modifiers=2
----
prtMethods: length=1
方法名称:builder, 参数数量:0, modifiers=9

这里出现了 两个内部类:BaseSuperBuilderVOBuilder(modifiers=1033)、BaseSuperBuilderVOBuilderImpl(modifiers=26)。

Eclipse的快捷键 Ctrl+Shift + T 可以搜搜到 这两个类:ben发布于博客园

 

BaseSuperBuilderVOBuilder 的 类分析测试结果:

测试:class=class com.lib.webdemo.vo2.BaseSuperBuilderVO$BaseSuperBuilderVOBuilder
prtClasses: length=0
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo2.BaseSuperBuilderVO$BaseSuperBuilderVOBuilder, 参数数量:0, modifiers=1
----
prtFields: length=2
字段:supId, type=class java.lang.Integer, modifiers=2
字段:supName, type=class java.lang.String, modifiers=2
----
prtMethods: length=7
方法名称:toString, 参数数量:0, modifiers=1
方法名称:supId, 参数数量:1, modifiers=1
方法名称:build, 参数数量:0, modifiers=1025
方法名称:supName, 参数数量:1, modifiers=1
方法名称:access$1, 参数数量:1, modifiers=4104
方法名称:access$0, 参数数量:1, modifiers=4104
方法名称:self, 参数数量:0, modifiers=1028

相比于使用@Builder,多了 access$1、access$0、self 3个方法ben发布于博客园

 

说明,BaseSuperBuilderVOBuilderImpl 是 private的,不做分析。

 

建立 BaseSuperBuilderVO 对象:

private static void testCreateBaseSuperBuilderVO() {
    BaseSuperBuilderVO base = BaseSuperBuilderVO.builder()
        .supId(999)
        .supName("super999")
        .build();
    cs.accept("BaseSuperBuilderVO base=" + base);
}

测试结果:

BaseSuperBuilderVO base=BaseSuperBuilderVO(supId=999, supName=super999)

 

子类使用 @SuperBuilder

新建子类 UserSuperBuilderVO:

import java.util.Date;
import java.util.List;

import lombok.ToString;
import lombok.experimental.SuperBuilder;

@SuperBuilder
@ToString(callSuper = true)
public class UserSuperBuilderVO extends BaseSuperBuilderVO {

	private Integer id;
	private String name;
	private List<String> tags;
	private Date createTime;
	
}

分析类 UserSuperBuilderVO、UserSuperBuilderVOBuilder 的测试结果:ben发布于博客园

测试:class=class com.lib.webdemo.vo2.UserSuperBuilderVO
prtClasses: length=2
内部类: com.lib.webdemo.vo2.UserSuperBuilderVO.UserSuperBuilderVOBuilder, com.lib.webdemo.vo2.UserSuperBuilderVO$UserSuperBuilderVOBuilder, UserSuperBuilderVOBuilder, com.lib.webdemo.vo2.UserSuperBuilderVO$UserSuperBuilderVOBuilder, modifiers=1033
内部类: com.lib.webdemo.vo2.UserSuperBuilderVO.UserSuperBuilderVOBuilderImpl, com.lib.webdemo.vo2.UserSuperBuilderVO$UserSuperBuilderVOBuilderImpl, UserSuperBuilderVOBuilderImpl, com.lib.webdemo.vo2.UserSuperBuilderVO$UserSuperBuilderVOBuilderImpl, modifiers=26
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo2.UserSuperBuilderVO, 参数数量:1, modifiers=4
----
prtFields: length=4
字段:id, type=class java.lang.Integer, modifiers=2
字段:name, type=class java.lang.String, modifiers=2
字段:tags, type=interface java.util.List, modifiers=2
字段:createTime, type=class java.util.Date, modifiers=2
----
prtMethods: length=2
方法名称:toString, 参数数量:0, modifiers=1
方法名称:builder, 参数数量:0, modifiers=9


测试:class=class com.lib.webdemo.vo2.UserSuperBuilderVO$UserSuperBuilderVOBuilder
prtClasses: length=0
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo2.UserSuperBuilderVO$UserSuperBuilderVOBuilder, 参数数量:0, modifiers=1
----
prtFields: length=4
字段:id, type=class java.lang.Integer, modifiers=2
字段:name, type=class java.lang.String, modifiers=2
字段:tags, type=interface java.util.List, modifiers=2
字段:createTime, type=class java.util.Date, modifiers=2
----
prtMethods: length=13
方法名称:name, 参数数量:1, modifiers=1
方法名称:toString, 参数数量:0, modifiers=1
方法名称:id, 参数数量:1, modifiers=1
方法名称:tags, 参数数量:1, modifiers=1
方法名称:createTime, 参数数量:1, modifiers=1
方法名称:build, 参数数量:0, modifiers=1025
方法名称:build, 参数数量:0, modifiers=4161
方法名称:access$3, 参数数量:1, modifiers=4104
方法名称:access$5, 参数数量:1, modifiers=4104
方法名称:access$2, 参数数量:1, modifiers=4104
方法名称:access$4, 参数数量:1, modifiers=4104
方法名称:self, 参数数量:0, modifiers=4164
方法名称:self, 参数数量:0, modifiers=1028

UserSuperBuilderVO多了两个内部类,

UserSuperBuilderVOBuilder有13个方法,其中access$2~5(access$0~1 在 父类中),两个build,两个self。

 

创建子类对象,可以看到 父类的属性也在了:supId、supName

 

小结

@SuperBuilder 用在了 父类、子类上,可以成功创建父子类对象。

不过,这个功能属于试验性质的,暂无更多精时去探究。ben发布于博客园

 

4、父类用@Data、子类用@Builder(可行)

新建父类BaseData2VO、子类UserBuilder2VO:

// 1、BaseData2VO
import lombok.Data;

@Data
public class BaseData2VO {

	private Integer supId;
	private String supName;
	
}

// 2、UserBuilder2VO
import java.util.Date;
import java.util.List;

import lombok.Builder;
import lombok.ToString;

@Builder
@ToString(callSuper = true)
public class UserBuilder2VO extends BaseData2VO {

	private Integer id;
	private String name;
	private List<String> tags;
	private Date createTime;
	
}

执行 子类UserBuilder2VO 的类分析:

测试:class=class com.lib.webdemo.vo2.UserBuilder2VO
prtClasses: length=1
内部类: com.lib.webdemo.vo2.UserBuilder2VO.UserBuilder2VOBuilder, com.lib.webdemo.vo2.UserBuilder2VO$UserBuilder2VOBuilder, UserBuilder2VOBuilder, com.lib.webdemo.vo2.UserBuilder2VO$UserBuilder2VOBuilder, modifiers=9
----
prtConstructors: length=1
构造方法名称:com.lib.webdemo.vo2.UserBuilder2VO, 参数数量:4, modifiers=0
----
prtFields: length=4
字段:id, type=class java.lang.Integer, modifiers=2
字段:name, type=class java.lang.String, modifiers=2
字段:tags, type=interface java.util.List, modifiers=2
字段:createTime, type=class java.util.Date, modifiers=2
----
prtMethods: length=2
方法名称:toString, 参数数量:0, modifiers=1
方法名称:builder, 参数数量:0, modifiers=9

注意,这里的 UserBuilder2VOBuilder 不能执行上面的类分析,和单独使用 @Builder 注解类不同。ben发布于博客园

 

创建UserBuilder2VO对象:父类的属性需要使用 setter 方法设置

private static void testCreateDataBuilderVO() {
    cs.accept("\n\n测试:testCreateDataBuilderVO...");
    UserBuilder2VO user = UserBuilder2VO.builder()
        // 子
        .id(2)
        .name("sub2")
        .tags(new ArrayList<>())
        .createTime(new Date())
        .build();
    // 父
    user.setSupId(999);
    user.setSupName("super999");
    cs.accept("UserBuilder2VO user=" + user);
}

测试结果:

测试:testCreateDataBuilderVO...
UserBuilder2VO user=UserBuilder2VO(super=BaseData2VO(supId=999, supName=super999), id=2, name=sub2, tags=[], createTime=Fri Dec 02 20:38:49 CST 2022)

 

小结

可以用这种方式,只不过父类属性需要使用 setter方法设置。ben发布于博客园

 

参考资料

1、Lombok 中@Builder 的使用

https://www.cnblogs.com/minmin123/p/14368725.html

2、java Lombok下解决@Builder继承解决方法(@SuperBuilder)

http://www.manongjc.com/detail/28-quhwksxdbgivhva.html

 

ben发布于博客园

 

posted @ 2022-12-02 23:27  快乐的凡人721  阅读(1143)  评论(0编辑  收藏  举报