【问题标题】:How to create a builder for third party POJO?如何为第三方 POJO 创建构建器?
【发布时间】:2022-01-17 20:00:07
【问题描述】:

如何为第三方类创建 Lombok 构建器(即我无法修改其源代码)?

我有一个无法更改的现有课程:

public class ThirdPartyPojo {
    // one of many properties
    private String name;

    public ThirdPartyPojo() {
        // default no-args constructor
    }

    String getName() {
        return this.name;
    }

    void setName(String name) {
        this.name = name;
    }

    // many more getters and setters
}

现在我想创建一个@Builder,以便获得一个流畅的构建器 API,以简化使用默认值的ThirdPartyPojo 的实例化。

这是我尝试过的:

@Builder
public class ThirdPartyPojoBuilder extends ThirdPartyPojo {

    @Default
    private String name = "default name";

    // many more default values for other properties
}

代码编译,我可以引用构建器,例如

ThirdPartyPojo pojoWithDefaultName = ThirdPartyPojoBuilder.builder().build();
ThirdPartyPojo pojoWithCustomName = ThirdPartyPojoBuilder.builder().name("custom name").build();

System.out.println(pojoWithDefaultName.getName());
System.out.println(pojoWithCustomName.getName());

但是,这不起作用,因为 getName()pojoWithDefaultNamepojoWithCustomName 返回 null

【问题讨论】:

  • 尝试在实体上添加@Builder and @Data ( @Setter , @Getter )
  • @DilermandoLima 你能详细说明一下吗?您是否建议我将这些注释添加到ThirdPartyPojo?这是一个外部依赖,所以我不能修改它的源代码。

标签: java lombok


【解决方案1】:

基于pirho's answer,我找到了一个可行的解决方案,它也尊重默认值。

  1. 扩展第三方类
  2. 在类级别添加@Builder注解
  3. 添加任何应该由构建器配置的字段
  4. 添加@Default 并将值分配给任何应具有默认值的字段
  5. 添加一个所有参数匹配所有字段的构造函数
  6. 为每个构造函数参数添加this.set*(...)

例如


@Builder
public class ThirdPartyPojoBuilder extends ThirdPartyPojo {
    @Default
    private String name = "default name" 

    public ThirdPartyPojoBuilder(String name) {
        this.setName(name);
    }
}

也支持默认值:

ThirdPartyPojo pojoWithDefaultName = ThirdPartyPojoBuilder.builder().build();
ThirdPartyPojo pojoWithCustomName = ThirdPartyPojoBuilder.builder().name("custom name").build();

System.out.println(pojoWithDefaultName.getName()); // prints "default name"
System.out.println(pojoWithCustomName.getName());  // prints "custom name"

【讨论】:

    【解决方案2】:

    恐怕没有简单的方法让 Lombok 以您可能想要的方式自动生成构建器。 Lombok @Builder 的一般做法是:

    最后,将@Builder 应用到一个类就好像你将@AllArgsConstructor(access = AccessLevel.PACKAGE) 加到这个类中,并将@Builder 注解应用到这个全参数构造器。

    这就是 - 我认为 - 你能做的所有事情:

    public class ThirdPartyPojoBuilder extends ThirdPartyPojo {
        @Builder
        public ThirdPartyPojoBuilder(String name) {
            this.setName(name);
        }
    }
    

    那么就有可能——例如:

    var thirdPartyPojo = ThirdPartyPojoBuilder.builder().name("A Name").build();
    

    【讨论】:

    • 谢谢,这在name()被明确设置的情况下有效。但是,它似乎并不尊重@Default?只执行var thirdPartyPojo = ThirdPartyPojoBuilder.builder().build(); 会导致name == null 尽管我已经配置了@Default private String name = "default name";
    • 我通过将@Builder注解从构造函数移动到类级别找到了解决方案,参见my answer
    • @matsev 抱歉,不知何故错过了默认值,但很高兴这有帮助。
    猜你喜欢
    • 2018-08-29
    • 2019-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    • 2016-03-24
    相关资源
    最近更新 更多