英文:
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("XYZ");
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("XYZ")
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:
<T> void consumeIfNonNull(@Nullable T value, Consumer<? super T> 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论