使用Optionals对多个属性进行Java null检查



在java 11上,对同一对象的多个字段进行空检查的最有效方法是什么?我选择了选项,但我不知道如何将它们与同一对象的更多字段一起使用

Map<String, NestedQuery> nested = new HashMap<>();
if (getSentDate() != null) {
if (getSentDate().getFrom() != null && getSentDate().getTo() != null) {
nested.put(...); 
}
}
return nested;

在我的例子中,getSentdate()返回一个具有getFrom()getTo()的对象,这两个值可能是也可能不是空

我试过这样做,但在if子句中使用.ifPresent是一个很大的no

Map<String, NestedQuery> nested = new HashMap<>();
Optional.ofNullable(getSentDate())
.ifPresent(sentDate -> {
Optional<String> from = Optional.ofNullable(sentDate.getFrom());
Optional<String> to = Optional.ofNullable(sentDate.getTo());
if(from.isPresent() && to.isPresent()){
nested.put(...);
}
});
return nested;

正如上面评论中所说,您的原始代码实际上非常高效(我们可能需要一些有效性标准(:

if (getSentDate() != null) {
if (getSentDate().getFrom() != null && getSentDate().getTo() != null) {

但是,如果您真的想使用Optional来消除一些的空检查,那么只使用一个就足够了:

Optional.ofNullable(getSentDate())
.filter(sentDate -> Objects.nonNull(sentDate.getFrom()))
.filter(sentDate -> Objects.nonNull(sentDate.getTo())) 
.ifPresent(date -> nested.put(...)); 

在这种情况下,只有当满足所有三个条件时才执行.ifPresent(date -> nested.put(...))getSentDate()不是nullsentDate.getFrom()不是nullsentDate.getTo()也不是null。然而,我们仍然有一个null检查,并且我们正在"滥用"Objects#nonNull方法,因为:

API注意:此方法可用作谓词、筛选器(Objects::nonNull(

这方面的等价物是

Optional.ofNullable(getSentDate())
.filter(sentDate -> sentDate.getFrom() != null)
.filter(sentDate -> sentDate.getTo() != null) 
.ifPresent(date -> nested.put(...)); 

请注意,这实际上"违反"了可选使用

API注意:Optional主要用于表示"无结果"的明显需要,以及使用null可能导致错误的方法返回类型。

请尝试以下操作,此处NestedQuery具有可选的发送日期,SendDate具有可选的getFrom和getTo值。您可以使用ifpresent和ispresent来检查值是否存在

private interface SendDate {
Optional<Object> getFrom();
Optional<Object> getTo();
}
private interface NestedQuery {
public Optional<SendDate> getSendDate();
}
private static NestedQuery createNestedQuery() {
return Optional::empty;
}
public static void main(final String[] args) {
final Map<String, NestedQuery> nested = new HashMap<>();
final NestedQuery nestedQuery = createNestedQuery();
nestedQuery.getSendDate().ifPresent(sendDate -> {
if (sendDate.getFrom().isPresent() && sendDate.getTo().isPresent())
nested.put("", nestedQuery);
});
System.out.println(nested.toString());
}

尽管使用&amp;它的短路行为是在处理多个级别的属性时所能得到的最好的。尽管如此,对于单层嵌套,您可以很容易地引入一个实用程序,该实用程序符合其中没有一个属性为null的要求。

@SafeVarargs
static <T> boolean noneNull(T... args) {
return Arrays.stream(args).noneMatch(Objects::isNull);
}

并将其用作

if(noneNull(sentDate.getFrom(), sentDate.getTo())) {
nested.put(...)
}

并且注意,不涉及Optional,这通常对于空对象的检查是不需要的。

最新更新