orElse-Branch中的可选抛出exception

所以我正在使用Optionals,并遇到了一个奇怪的行为。 我想知道这是否真的是一个强烈的“function”或者什么……奇怪…

下面是给出的示例:我有一个带有Optional的方法,其中orElse我想评估另一个可选项。 如果其他Optional不存在,我将引发IllegalArgumentException:

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

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

使用java7方法来解决这种行为并不是什么大问题:

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

有没有其他人以前经历过这种行为? 这真的是选项应该表现的方式吗?

这是预期的行为。 orElse期望一个类型为T的参数(无论Optional的generics类型是什么。 orElseThrow返回一个T ,因此需要首先计算它,以便将参数传递给orElse

你想要的是orElseGet ,它取一个Supplier 。 这将延迟执行orElseThrow直到firstOptionalVar已被检查。

所以你的代码应该是这样的:

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

这会将orElseThrow部分转换为lambda,并且仅在需要时才进行评估(即,当firstOptionalVar没有要获取的值时)。

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

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

我看不到使用Optional标准方法解决这个问题的简单方法,你总是可以从两个选项中构建一个流并获得第一个元素或者抛出一个exception,但它似乎有点复杂。