在 Java 8 中使用 Optional 进行多次空值检查

Multiple null checks using Optional in Java 8

我想使用 Java 8 的多个 ifelse 语句来简化下面的代码。 有没有办法使用一些 Java 8 功能来完全摆脱它们,例如Optional? 我试图在这里找到一些东西,但找不到答案。

LocalDateTime beDate = someDate;
LocalDateTime aeDate = someDate;
LocalDateTime eDate;

if (beDate == null && aeDate == null) {
    eDate = null;
}
else if (beDate != null && aeDate == null) {
    eDate = beDate;
}
else if (beDate == null && aeDate != null) {
    eDate =  aeDate;
}
else if (beDate != null && aeDate != null && 
        (beDate.isEqual(aeDate) || beDate.isBefore(aeDate))) {
    eDate = beDate;
}
else {
    eDate = aeDate;
}

您可以使用 Optional.ofNullable,但我不建议这样做。

将所有内容包装在 Optional 中不会使其更易于阅读。您必须进行 null 检查,因此您将 obj == null 替换为 obj.isEmpty()(或 java 8 中的 obj.isEmpty())。

这里的逻辑很难理解。相反,更直接地表达你的意图:

private static final Comparator<ChronoLocalDateTime<?>> EARLIEST_PRESENT = 
    Comparator.nullsLast(Comparator.naturalOrder());

LocalDateTime eDate = BinaryOperator.minBy(EARLIEST_PRESENT).apply(beDate, aeDate);

(请注意,对来自 ComparatorBinaryOperator 的元素进行静态导入将使这一点更加清晰。)

您的条件是多余的,因为结果只是两种可能结果之一:

if (beDate == null && aeDate == null) {
    eDate = null;
}
else if (beDate != null && aeDate == null) {
    eDate = beDate;
}
...

在这里,eDatebeDate 的内容相同,无论 null 与否。所以 if(aeDate == null) eDate = beDate; 就足够了。在所有其他情况下,您分配 aeDate,只有一个例外:

...
else if (beDate != null && aeDate != null && 
        (beDate.isEqual(aeDate) || beDate.isBefore(aeDate))) {
    eDate = beDate;
}
...

我们可以将beDate.isEqual(aeDate) || beDate.isBefore(aeDate)简化为aeDate.isAfter(beDate)

所以整个语句可以写成:

LocalDateTime eDate
    = aeDate == null || (beDate != null && aeDate.isAfter(beDate))? beDate: aeDate;

中的||是短路的,也就是说,只有当左侧计算为false时,右侧才被计算,所以当左侧为[=22=时], 右侧隐含 aeDate != null 并且不需要重复。

因此,当 aeDatenull(前两个 if 语句)或两者都不是 [时,eDate 将获得 beDate 的值=15=]和aeDatebeDate之后(对方引用if语句),否则取aeDate的值。

运算符优先级使括号变得不必要,但为了清楚起见,保留它们也是有效的。

您可以使用来自 Apache Commons 的 ObjectUtils::min

LocalDateTime eDate = ObjectUtils.min(aeDate, beDate);

解决方案是一页纸,易于阅读。