在构建器中对特定字段进行条件设置。

huangapple go评论74阅读模式
英文:

Conditional setting of certain fields in a builder

问题

以下是翻译好的部分:

我有一个具有构建器的遗留Java类 - 我不能更改此类。

构建器的一些setter在null输入时会抛出异常:

public Cat.Builder setOwnerName(String value) {
    if (value == null) {
        throw new NullPointerException();
    } else {
        this.ownerName = value;
        this.onChanged();
        return this;
    }
}

我正在尝试从另一个类创建该Cat - 使用可能具有null值的外部对象填充相关字段:

Cat cat = Cat.newBuilder()
            .setXYZ("XYZ")
            .setOwnerName(inputFromUser.getOwnerName())
            .build();

由于inputFromUser.getOwnerName()有时为null,构建器会抛出异常。

我试图找到一种优雅的方法来有条件地设置非null字段中的ownerName(或任何其他字段)。

英文:

I have a legacy Java class with a builder - I can't change this class.

Some of the setters of the builder are throwing an exception on null input:

     public Cat.Builder setOwnerName(String value) {
        if (value == null) {
            throw new NullPointerException();
        } else {
            this.ownerName = value;
            this.onChanged();
            return this;
        }
     }

I'm trying to create that Cat from another class - using an external object that may, or may not, have a null value in the relevant field:

  Cat cat = Cat.newBuilder()
            .setXYZ("XYZ")
            .setOwnerName(inputFromUser.getOwnerName())
            .build();

And since the inputFromUser.getOwnerName() is sometimes null, the builder throws an exception.

I'm trying to find an elegant way to conditionally set or not the ownerName (or any other of the non-null fields).

答案1

得分: 3

Cat.Builder builder = Cat.newBuilder()
    .setXYZ("XYZ");
Optional.ofNullable(inputFromUser.getOwnerName())
    .ifPresent(builder::setOwnerName);
// 重复以上语句以填充所有可选字段
Cat cat = builder.build();
英文:
Cat.Builder builder = Cat.newBuilder()
    .setXYZ("XYZ");
Optional.ofNullable(inputFromUser.getOwnerName())
    .ifPresent(builder::setOwnerName);
// repeat above statement for all optional fields
Cat cat = builder.build();

答案2

得分: 1

你不必使用调用链来调用构建器:

Cat.Builder catBuilder = Cat.newBuilder();
catBuilder.setXYZ("XYZ");
catBuilder.setOwnerName(inputFromUser.getOwnerName());
Cat cat = catBuilder.build();

(你可能不需要。对于构建器方法并没有要求返回自身,但如果不这样做可能会有点不寻常)。

所以,可以这样编写,并在需要时加入条件:

Cat.Builder catBuilder = Cat.newBuilder();
catBuilder.setXYZ("XYZ");
if (inputFromUser.getOwnerName() != null) {
  catBuilder.setOwnerName(inputFromUser.getOwnerName());
}
Cat cat = catBuilder.build();

如果你想更加函数式一些,可以编写一个类似这样的方法:

<T> void consumeIfNonNull(@Nullable T value, Consumer<? super T> consumer) {
  if (value != null) consumer.accept(value);
}

然后可以这样使用:

consumeIfNonNull(inputFromUser.getOwnerName(), catBuilder::setOwnerName);

我认为在调用点上这样做比使用 Optional 更整洁,但因人而异。

英文:

You don't have to use call chaining to invoke a builder:

Cat.Builder catBuilder = Cat.newBuilder();
catBuilder.setXYZ(&quot;XYZ&quot;);
catBuilder.setOwnerName(inputFromUser.getOwnerName());
Cat cat = catBuilder.build();

(You probably don't. There's no requirement for a Builder method to return itself, but it would be a little unusual if it didn't).

So, write it like this, and put a conditional where needed.

Cat.Builder catBuilder = Cat.newBuilder();
catBuilder.setXYZ(&quot;XYZ&quot;)
if (inputFromUser.getOwnerName() != null) {
  catBuilder.setOwnerName(inputFromUser.getOwnerName());
}
Cat cat = catBuilder.build();

If you wanted to be a bit more functional, you could write a method like:

&lt;T&gt; void consumeIfNonNull(@Nullable T value, Consumer&lt;? super T&gt; consumer) {
  if (value != null) consumer.accept(value);
}

and then do:

consumeIfNonNull(inputFromUser.getOwnerName(), catBuilder::setOwnerName);

I think this is neater at the call site than using an Optional, but to each their own.

huangapple
  • 本文由 发表于 2020年5月19日 20:04:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/61890615.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定