如何为第三方 POJO 创建构建器?

How to create a builder for third party POJO?

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

我有一个无法更改的 class:

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());

但是,这对于 pojoWithDefaultNamepojoWithCustomName 都不起作用,因为 getName() returns null

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

Finally, applying @Builder to a class is as if you added @AllArgsConstructor(access = AccessLevel.PACKAGE) to the class and applied the @Builder annotation to this all-args-constructor.

这就是 - 我认为 - 你能做的一切:

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

那么就可以了——比如:

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

基于,我找到了一个可行的解决方案,也支持默认值。

  1. 扩展第三方class
  2. 在 class 级别添加 @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"