Optional in orElse-Branch throws Exception [duplicate]

匆匆过客 提交于 2019-12-19 06:45:38

问题


So I'm working with Optionals and came across a strange behaviour. I want to know if this is really an intendet "feature" or something...odd...

Here is the given example: I've got a method with an Optional in whose orElse I want to evaluate an other optional. If the other Optional is not present, I'll raise an IllegalArgumentException:

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

Now if the secondOptionalVar is an empty Optional, it will raise an IllegalArgumentException, even if the firstOptionalVar is Present. This doesn't seem right to me. I would expect it to just raise an IllegalArgumentException if the firstOptionalVar would not be present.

It's not a big deal to get arround this behavior with java7-methods like:

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

Has anyone else experienced this behaviour before? Is this really the way optionals should behave?


回答1:


This is the intended behavior. orElse expects an argument of type T (whatever the generic type of the Optional is. orElseThrow returns a T, so it needs to be evaluated first, in order to pass the parameter into orElse.

What you want is orElseGet, which takes a Supplier<T>. That will delay execution of the orElseThrow until after firstOptionalVar has already been checked.

So your code should look like this:

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

That will turn the orElseThrow section into a lambda, and only evaluate it if it's needed (ie. when firstOptionalVar doesn't have a value to get).




回答2:


At the heart of everything, you're still only calling Java methods, and therefore the standard Java order of evaluation applies.

Specifically: secondOptionalVar.orElseThrow(IllegalArgumentException::new) has to be evaluated before the call to firstOptionalVar.orElse(), as it provides the argument of firstOptionalVar.orElse().

I can't see any easy way of resolving this with standard methods of Optional, you can always build a stream out of the two optionals and get the first element or else throw an exception, but it seems a bit convoluted.



来源:https://stackoverflow.com/questions/38571537/optional-in-orelse-branch-throws-exception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!