在 Java 8 中使用 Optional 进行多次空值检查
Multiple null checks using Optional in Java 8
我想使用 Java 8 的多个 if
和 else
语句来简化下面的代码。
有没有办法使用一些 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);
(请注意,对来自 Comparator
和 BinaryOperator
的元素进行静态导入将使这一点更加清晰。)
您的条件是多余的,因为结果只是两种可能结果之一:
if (beDate == null && aeDate == null) {
eDate = null;
}
else if (beDate != null && aeDate == null) {
eDate = beDate;
}
...
在这里,eDate
与 beDate
的内容相同,无论 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
并且不需要重复。
因此,当 aeDate
为 null
(前两个 if
语句)或两者都不是 [时,eDate
将获得 beDate
的值=15=]和aeDate
在beDate
之后(对方引用if
语句),否则取aeDate
的值。
运算符优先级使括号变得不必要,但为了清楚起见,保留它们也是有效的。
您可以使用来自 Apache Commons 的 ObjectUtils::min:
LocalDateTime eDate = ObjectUtils.min(aeDate, beDate);
解决方案是一页纸,易于阅读。
我想使用 Java 8 的多个 if
和 else
语句来简化下面的代码。
有没有办法使用一些 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);
(请注意,对来自 Comparator
和 BinaryOperator
的元素进行静态导入将使这一点更加清晰。)
您的条件是多余的,因为结果只是两种可能结果之一:
if (beDate == null && aeDate == null) {
eDate = null;
}
else if (beDate != null && aeDate == null) {
eDate = beDate;
}
...
在这里,eDate
与 beDate
的内容相同,无论 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
并且不需要重复。
因此,当 aeDate
为 null
(前两个 if
语句)或两者都不是 [时,eDate
将获得 beDate
的值=15=]和aeDate
在beDate
之后(对方引用if
语句),否则取aeDate
的值。
运算符优先级使括号变得不必要,但为了清楚起见,保留它们也是有效的。
您可以使用来自 Apache Commons 的 ObjectUtils::min:
LocalDateTime eDate = ObjectUtils.min(aeDate, beDate);
解决方案是一页纸,易于阅读。