2016-07-25 84 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的標準方法解決這個問題的簡單方法,你總是可以從兩個選項中構建一個流並獲得第一個元素或者拋出一個異常,但看起來有點複雜。