2016-07-25 9 views
3

私はOptionalsで作業していて、奇妙な動作を経験しました。私はこれが本当にインテンテッドの "機能"なのか、それとも奇妙なのかを知りたいと思っています...orElse-分岐オプションで例外をスローする例外

ここに与えられた例があります: 私はオプションのあるorElseのメソッドを持っています。その他のオプション。他のオプションが存在しない場合、私はIllegalArgumentExceptionを上げるでしょう:

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

をが空のオプションであれば今、それはfirstOptionalVarが存在する場合であっても、はIllegalArgumentExceptionが発生します。これは私にとっては正しいとは思わない。 firstOptionalVarが存在しない場合、IllegalArgumentExceptionを発生させるだけです。

それはのようなjava7-方法でこの動作arroundの取得するには大したことではないです:

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

は、他の誰の前に、この動作を経験していますか?これは本当にオプションが行動するべきか?

+0

'flatMap'は残念なことに反対です。 – biziclop

+2

例外に対するアンカーは、リンクされた質問または得られた回答で見つけることができます。実行したい "or"操作はJava 9で利用できることに注意してください:http://stackoverflow.com/questions/24599996/get-value-from-one-optional-or-another – Tunaki

+0

あなたの答えをありがとう。 @resuemanの解決策は私にとってはうまくいくはずですが、java9がこのケースをどのように処理するかを知ることは良いことです:) – Numbernick

答えて

6

これは意図した動作です。 orElseorElseThrowOptionalの一般的なタイプにかかわらずタイプT(の引数を期待Tを返しますので、orElseにパラメータを渡すために、最初に評価する必要があります。あなたが望む

orElseGet、あります。。Supplier<T>かかりfirstOptionalVarが既に確認された後までorElseThrowの実行を遅延することを

だからあなたのコードは次のようになります。

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

これはorElseThrowセクションをラムダに変え、必要ならば評価するだけです。 firstOptionalVarに取得する値がない場合)。

+2

Nice one。これは私が把握しようとしてきた解決策です。 :) – biziclop

+1

ありがとうございました。それはまさに私が探していたものです。 – Numbernick

3

あなたはまだJavaメソッドを呼び出しているだけなので、標準Java評価の順番が適用されます。

具体的に:secondOptionalVar.orElseThrow(IllegalArgumentException::new)は、それがfirstOptionalVar.orElse()の引数を提供して、firstOptionalVar.orElse()前にコールを評価する必要があります。

Optionalの標準的な方法でこれを解決する簡単な方法はありません。いつも2つのオプションからストリームを作成して最初の要素を取得するか、例外をスローしますが、ちょっと複雑です。