Optional in orElse-Branch throws Exception

Optional in orElse-Branch throws Exception

所以我在使用 Optionals 时遇到了一个奇怪的行为。我想知道这是否真的是一个意图 "feature" 或什么...奇怪...

这是给定的例子: 我有一个带有 Optional 的方法,我想在其 orElse 中评估另一个可选值。如果另一个 Optional 不存在,我将引发 IllegalArgumentException:

firstOptionalVar.orElse(secondOptionalVar.orElseThrow(IllegalArgumentException::new));

现在,如果 secondOptionalVar 是一个空的 Optional,即使 firstOptionalVar 存在,它也会引发 IllegalArgumentException。这对我来说似乎不对。如果 firstOptionalVar 不存在,我希望它只会引发 IllegalArgumentException。

用 java7 方法解决这个问题没什么大不了的:

firstOptionalVar.isPresent() ? firstOptionalVar.get() : secondOptionalVar.orElseThrow(IllegalArgumentException::new);

其他人以前遇到过这种行为吗?这真的是可选项的行为方式吗?

这是预期的行为。 orElse 期望类型为 T 的参数(无论 Optional 的通用类型是什么。orElseThrow returns a T,因此它需要首先进行评估,以便将参数传递给 orElse.

你要的是orElseGet,需要一个Supplier<T>。这将延迟 orElseThrow 的执行,直到 firstOptionalVar 已经被检查。

因此您的代码应如下所示:

firstOptionalVar.orElseGet(() -> secondOptionalVar.orElseThrow(IllegalArgumentException::new));

这会将 orElseThrow 部分变成一个 lambda,并且仅在需要时对其进行评估(即当 firstOptionalVar 没有可获取的值时)。

在一切的核心,您仍然只调用 Java 方法,因此适用标准 Java 评估顺序。

具体来说:secondOptionalVar.orElseThrow(IllegalArgumentException::new) 必须在 调用 firstOptionalVar.orElse() 之前计算 ,因为它提供了 firstOptionalVar.orElse() 的参数。

我看不出有什么简单的方法可以用 Optional 的标准方法解决这个问题,你总是可以用两个可选值构建一个流并获取第一个元素,否则抛出异常,但它好像有点绕。