2016-07-25 88 views
3

所以我正在使用Optionals并遇到了一个奇怪的行为。我想知道这是否真的是一个intendet“功能”或其他...奇怪...orElse分支抛出的可选异常

这里给出的例子: 我有一个方法,其中orElse我想要评估其他可选。如果其他可选是不存在的,我会养一个IllegalArgumentException:

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

现在,如果是空可选,它会引发一个IllegalArgumentException,即使firstOptionalVar是存在的。这对我来说并不合适。如果firstOptionalVar不存在,我希望它会引发IllegalArgumentException。

这不是什么大不了的事得到角落找寻这种行为与java7的方法,如:

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

有没有其他人经历过这种行为?这是否真的是可选方式应该表现的方式?

+0

'flatMap'不幸的是相反。 – biziclop

+2

可以在链接问题或答案中找到例外情况。请注意,您要执行的“或”操作将在Java 9上提供:http://stackoverflow.com/questions/24599996/get-value-from-one-optional-or-another – Tunaki

+0

谢谢您的回答。 @resueman的解决方案将为我工作,但很高兴知道java9将如何处理这种情况:) – Numbernick

回答

6

这是预期的行为。 orElse预计T型(无论泛型类型的Optional的是一个说法。orElseThrow返回T,所以它需要首先评估,以参数传递到orElse

你想要的是orElseGet,这。需要Supplier<T>这将延缓orElseThrow执行后firstOptionalVar已经检查到

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

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

这会将orElseThrow部分转换为lambda表达式,并且只在需要时才对其进行评估(即。当firstOptionalVar没有得到的值)。

+2

好的。这是我一直试图找出的解决方案。 :) – biziclop

+1

非常感谢。这正是我所期待的。 – Numbernick

3

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

具体做法是:secondOptionalVar.orElseThrow(IllegalArgumentException::new)具有待评估之前调用firstOptionalVar.orElse(),因为它提供的firstOptionalVar.orElse()的论点。

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