Java 记录自定义构造函数选择参数

Java Record Custom Constructor Selective Parameters

我有一条记录:

public record Thing(
   Boolean field1,
   EnumType field2,
   int field3,
   String, field4
   . . .

我向 Thing 添加了很多新字段,这破坏了我所有使用规范构造函数的代码,并且字段堆积如山,这使得规范构造函数越来越难以使用。

我想做的是能够为任意字段传递特定值:

new Thing(field3 = 1, field4 = "XXX");
new Thing(field1 = true, field2 = ENUMVALUE);

现在,我知道我可以做这样的构造函数:

Thing(int i, String s) ...
Thing(Boolean b, EnumType, e) ...
. . .
new Thing(1, "XXX");
new Thing(true, ENUMVALUE);

但这确实是一种不知道我要为哪些字段覆盖默认值的情况。到目前为止,我唯一能想到的就是将 Thing 变成一个常规对象,这样我就可以做类似的事情:

new Thing().setField1(true).setField4("Blah");

这有点令人失望,因为我不希望值在初始化后可变。

不幸的是 Java 没有命名参数(至少目前是这样)。我们可以做些什么来克服这个缺失的语言功能是使用 builder pattern.

对于记录,我们可以这样做:

public record Thing(Boolean field, int field2, String field3) {

    private Thing(ThingBuilder thingBuilder) {
        this(thingBuilder.field, thingBuilder.field2, thingBuilder.field3);
    }

    public static class ThingBuilder {
        // We can set default values for the fields
        private Boolean field = false;
        private int field2;
        private String field3 = "";

        public ThingBuilder() {}

        public ThingBuilder field(Boolean field) {
            this.field = field;
            return this;
        }

        public ThingBuilder field2(int field) {
            this.field2 = field;
            return this;
        }

        public ThingBuilder field3(String field) {
            this.field3 = field;
            return this;
        }

        public Thing build() {
            return new Thing(this);
        }
    }
}

我们可以通过以下方式构建 Thing 个实例:

Thing thing = new Thing.ThingBuilder().field(true).field2(2).field3("some string").build();

此外,我们可以省略一些字段并让它们使用默认值:

Thing thing = new Thing.ThingBuilder().field3("some string").build();