2017-04-23 42 views
7

我不能找到一種方法,做Java的Optional如下:Java可選可用於流量控制嗎?

if (SOME_OBJECT != null) { 
    doSomething(SOME_OBJECT); 
} else { 
    doSomethingElse(); 
} 

通過使用Optional,我的意思並不是指與Optional.ofNullable(SOME_OBJECT).isPresent()更換SOME_OBJECT == null,這更長的語法比如果爲null?只需勾選。

什麼我希望是這樣的:

Optional.ofNullable(SOME_OBJECT) 
    .ifPresent(this::doSomething) 
    .orElse(this::doSomethingElse); 

我找不到像我剛寫的API。它存在嗎?如果是這樣,那是什麼?如果不是,爲什麼不呢? :)

代碼的第二件看起來像一個反模式:(爲什麼?也許是Java的建築師防止故意此語法...

+1

它似乎令人驚訝'ifPresent'不返回'Optional',而且似乎沒有'ifAbsent'。 –

+4

我認爲第二塊代碼可能是反模式,因爲它執行三個方法調用,並且似乎也執行了更多的檢查('ifPresent'和'orElse'必須重新檢查'ofNullable'的結果。至少像複製一樣複雜,並且會更難以維護,所有的缺點(即使很小),沒有任何好處 – markspace

+0

@markspace:我傾向於將'Optional'看作一個整體。 )但是我沒有在憤怒中使用它(我現在還沒有做過任何嚴肅的Java),所以我的觀點是反動的和不知情的...... :-) –

回答

8

在本Blog Article選配提到將在Java中9得到一個新的了Methode所以與Java 8 void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction);你沒有類似的東西的時刻。

+1

我認爲閱讀'x == null'比'ifPresentOrElse'更容易。也許當與流相結合時,增值更明顯? –

+0

另一個來源(來自Java 9官方文檔):https://docs.oracle.com/javase/9​​/docs/api/java/util/Optional.html#ifPresentOrElse-java.util.function.Consumer-java.lang .Runnable- –

2

正如所說的Java 8不具有結構做的正是你想要的。

我知道,這是醜陋的,遠不如可讀比簡單的if/then/else,但你可以做到這一點:

Optional.ofNullable(someObject) 
     .map(obj -> { 
      System.out.println("present"); 
      return obj; 
      }) 
     .orElseGet(() -> { 
      System.out.println("not present"); 
      return null; 
      }); 

唯一的副作用是你總是返回一些東西。
或者另一方面,您可以乾淨地處理案件isPresent()

Optional.ofNullable(someObject).ifPresent(obj -> { 
    System.out.println("present"); 
}); 
+0

儘管可能,但我不能想到這是一個好主意的情況。它比'if-else'更復雜,未使用的返回值進一步混淆了意圖。 (除了濫用'map()'和'orElseGet()'以獲得副作用外)。 – Hulk

+0

正確...我只是想了解我們是否可以避免僅限於Java 8的這種限制。但結果有點太難看了:) – freedev

2

作爲BdoubleB97(Bdubzz)所述,爪哇9將實施Optional#ifPresentOrElse這將需要一個Consumer<T>如果Optional<T>存在將應用,並且如果Optional<T>是空的,這將被執行的Runnable

您可以立即更新到Java 9月初訪問的身材,或者你可以建立自己的方法有以下幾點:

public <T> void ifPresentOrElse(Optional<T> optional, Consumer<? super T> action, Runnable emptyAction) { 
    if (optional.isPresent()) { 
     action.accept(optional.get()); 
    } else { 
     emptyAction.run(); 
    } 
}