为 NullPointerException 编写多重检查的替代方法,JAVA 8
Alternate way to code multiple checks for NullPointerException, JAVA 8
在 JAVA 8 中是否有更好的编码方式?
if (info1 != null && info1.getId() != null && info1.getPartyNumber()!= null) {
billing.setSenderId(info1.getId());
billing.setSenderNumber(info1.getPartyNumber());
}
if (info2 != null && info2.getId() != null && info2.getPartyNumber()!= null) {
billing.setReceiverId(info2.getId());
billing.setSellerNumber(info2.getPartyNumber());
}
..
..
提前致谢。
注意:我调查了 Optional.ofNullable()
但不确定这是否真的有助于进行多次检查?
这是我能想到的最好的。我会让你决定它是否更干净:
Optional<Info> oInfo1 = Optional.ofNullable(info1);
oInfo1.map(Info::getId).ifPresent(billing::setSenderId);
oInfo1.map(Info::getPartyNumber).ifPresent(billing::setSenderNumber);
Optional<Info> oInfo2 = Optional.ofNullable(info2);
oInfo2.map(Info::getId).ifPresent(billing::setReceiverId);
oInfo2.map(Info::getPartyNumber).ifPresent(billing::setSellerNumber);
请注意,这与原来的略有不同,它可能会设置一个字段,即使另一个字段为空。
如果你想用 Optional
重写它,它可能看起来像这样:
Optional.ofNullable(info1)
.filter(i -> i.getId() != null)
.filter(i -> i.getPartyNumber() != null)
.ifPresent(i -> {
billing.setSenderId(info1.getId());
billing.setSenderNumber(info1.getPartyNumber());
});
编辑
只有当 info1
不是 null
并且指定为 Optional.filter
参数的所有条件都匹配时,我们才处理它。因此只有在 info1 != null
和 info1.getId() != null
和 info1.getPartyNumber() != null
的情况下, Consumer
才会被执行。这是对多个检查进行编码的替代方法。它执行您的代码执行的操作。
同样的方法适用于info2
。
编辑
Optional
的流畅 API 与多行符号相结合,将每个条件分解为一行。 IMO 这使得代码易于阅读,因此易于理解。它尽可能地保持了原始代码的简洁明了,并且仍然以相同的方式运行。
如果您在源代码中复制代码,您应该三思而后行。我认为你的测试很好,但我会为它制定一个方法,所以你的代码看起来像这样:
如果(完成(信息1)
{
....
}
如果(完成(信息2)
{
....
}
如果您的多次重复遵循一个精确的模式(例如,每个奇数重复设置一个 receiver
,否则 sender
)或者这个模式可以提取到 Set<Integer>
,您可以使用Map<Integer, Info>
其中键是 Info
的 ID,遍历它并仅设置所选项目。
List<Info> list = ... // List of Info
Map<Integer, Info> map = list.stream() // Stream
.filter(Objects::nonNull) // Filter null values
.filter(i -> i.getId() != null && i.getPartyNumber() != null) // Filter null fields
.collect(Collectors.toMap(Info::getId, i -> i)); // Collect to Map<Integer, Info>
for (int i=0; i<10; i++) { // The number of repetitions
if (map.containsKey(i)) { // If the ID was not filtered
Info info = map.get(i); // Get the Info
// Here the pattern comes
if (i % 2 == 0) { // you can either compare with a
// predefined Set of IDs
billing.setSenderId(info.getId());
billing.setSenderNumber(info.getPartyNumber()); // Sender
} else {
billing.setReceiverId(info.getId()); // Receiver
billing.setSellerNumber(info.getPartyNumber());
}
}
}
解决方案会有所不同,取决于可能设置的数量以及 sender
和 receiver
。此外,模式的计算可能基于不同的逻辑——我建议针对 ex 进行验证。 Set<Integer> senders
将包含适合设置为发送者的 ID,同样适用于接收者和其他可能性。
- 优点:
- 无论
Info
次迭代,解决方案的长度保持不变(除了将所有Info
s收集到输入list
)。
- 避免臃肿的代码和重复。
- 缺点:
- 你得考虑一下计算和逻辑来区分要设置什么。
- 可能看起来凌乱且难以阅读。
在 JAVA 8 中是否有更好的编码方式?
if (info1 != null && info1.getId() != null && info1.getPartyNumber()!= null) {
billing.setSenderId(info1.getId());
billing.setSenderNumber(info1.getPartyNumber());
}
if (info2 != null && info2.getId() != null && info2.getPartyNumber()!= null) {
billing.setReceiverId(info2.getId());
billing.setSellerNumber(info2.getPartyNumber());
}
..
..
提前致谢。
注意:我调查了 Optional.ofNullable()
但不确定这是否真的有助于进行多次检查?
这是我能想到的最好的。我会让你决定它是否更干净:
Optional<Info> oInfo1 = Optional.ofNullable(info1);
oInfo1.map(Info::getId).ifPresent(billing::setSenderId);
oInfo1.map(Info::getPartyNumber).ifPresent(billing::setSenderNumber);
Optional<Info> oInfo2 = Optional.ofNullable(info2);
oInfo2.map(Info::getId).ifPresent(billing::setReceiverId);
oInfo2.map(Info::getPartyNumber).ifPresent(billing::setSellerNumber);
请注意,这与原来的略有不同,它可能会设置一个字段,即使另一个字段为空。
如果你想用 Optional
重写它,它可能看起来像这样:
Optional.ofNullable(info1)
.filter(i -> i.getId() != null)
.filter(i -> i.getPartyNumber() != null)
.ifPresent(i -> {
billing.setSenderId(info1.getId());
billing.setSenderNumber(info1.getPartyNumber());
});
编辑
只有当 info1
不是 null
并且指定为 Optional.filter
参数的所有条件都匹配时,我们才处理它。因此只有在 info1 != null
和 info1.getId() != null
和 info1.getPartyNumber() != null
的情况下, Consumer
才会被执行。这是对多个检查进行编码的替代方法。它执行您的代码执行的操作。
同样的方法适用于info2
。
编辑
Optional
的流畅 API 与多行符号相结合,将每个条件分解为一行。 IMO 这使得代码易于阅读,因此易于理解。它尽可能地保持了原始代码的简洁明了,并且仍然以相同的方式运行。
如果您在源代码中复制代码,您应该三思而后行。我认为你的测试很好,但我会为它制定一个方法,所以你的代码看起来像这样:
如果(完成(信息1) { .... } 如果(完成(信息2) { .... }
如果您的多次重复遵循一个精确的模式(例如,每个奇数重复设置一个 receiver
,否则 sender
)或者这个模式可以提取到 Set<Integer>
,您可以使用Map<Integer, Info>
其中键是 Info
的 ID,遍历它并仅设置所选项目。
List<Info> list = ... // List of Info
Map<Integer, Info> map = list.stream() // Stream
.filter(Objects::nonNull) // Filter null values
.filter(i -> i.getId() != null && i.getPartyNumber() != null) // Filter null fields
.collect(Collectors.toMap(Info::getId, i -> i)); // Collect to Map<Integer, Info>
for (int i=0; i<10; i++) { // The number of repetitions
if (map.containsKey(i)) { // If the ID was not filtered
Info info = map.get(i); // Get the Info
// Here the pattern comes
if (i % 2 == 0) { // you can either compare with a
// predefined Set of IDs
billing.setSenderId(info.getId());
billing.setSenderNumber(info.getPartyNumber()); // Sender
} else {
billing.setReceiverId(info.getId()); // Receiver
billing.setSellerNumber(info.getPartyNumber());
}
}
}
解决方案会有所不同,取决于可能设置的数量以及 sender
和 receiver
。此外,模式的计算可能基于不同的逻辑——我建议针对 ex 进行验证。 Set<Integer> senders
将包含适合设置为发送者的 ID,同样适用于接收者和其他可能性。
- 优点:
- 无论
Info
次迭代,解决方案的长度保持不变(除了将所有Info
s收集到输入list
)。 - 避免臃肿的代码和重复。
- 无论
- 缺点:
- 你得考虑一下计算和逻辑来区分要设置什么。
- 可能看起来凌乱且难以阅读。