2017-07-28 45 views
3

我有可選的問題,我不知道如何處理它。Java 8可選,而不是如果

public void check(String name) { 
    if (name != null) 
     doSomething(name); 
    else 
     doMore(); 
} 

如果到可選如何改變呢?

+13

你不! '可選'不應該被傳入方法中,它們僅用於返回可選值。你的代碼是完美的,因爲它現在是可能的(可能想添加一個'@ Nullable'註釋) – luk2302

+1

在這種情況下,你真的不能,但是如果你的其他東西是'doSomething(「」);'那麼'可選 name'可以像'doSomething(name.orElse(「」))一樣使用;' –

+0

在這種情況下利用方法重載可能會更好,所以不帶參數的check()方法會調用doMore()帶有@NonNull String名稱的check()方法只接受非空字符串。否則,請遵循Eugene或luk2302的建議。 – srborlongan

回答

12

有應該是一個非常整潔的方法,但目前在JDK-9 ...

public void check(String name){ 
    Optional.ofNullable(name) 
      .ifPresentOrElse(YourClass::doSomething, YourClass::doMore); 
} 

假設doSomethingdoMore是靜態的方法...如果沒有實例應該使用,如this::doSomethingthis::doMore

+0

我認爲它應該是'this :: doSomething'和'this :: doMore' – danielspaniol

+10

我會說這與* neat *非常相似。該代碼比原始代碼更長,更隱蔽。雖然技術上正確,但我會要求在Code Review中查看時更改它。 – luk2302

+0

@danielspaniol萬一這些方法不是靜態的 - 是的... – Eugene

6

雖然肯定是一個方法來創建使用Optional S也是一樣的代碼(例如見尤金的答案),你不應該在這裏(恕我直言)使用Optional秒。

要麼你會得到Optional傳遞給你的方法,這會給調用者帶來開銷,並且沒有真正理解爲什麼/爲什麼使用Optional引入。
或者您可以自己在方法中創建Optional。這更「好」,但非常麻煩,模糊了實際發生的事情,如果在代碼審查過程中遇到它,我會要求更改它。只需使用Optional和您當前的代碼來比較片段 - 您的代碼在字符方面可能較短,但很明顯發生了什麼。這裏使用Optionals的唯一好處是,它似乎成爲一個單線程,首先沒有什麼比可讀性更重要,而且無論如何,如果您要添加一些大括號,則無需它就可以實現。


底線:你的代碼是完全正常的,因爲它是。

+1

這是非常有爭議的......拒絕@Eugene的代碼,即在評論中沒有有效的技術論據。這只是一個品味問題,兩種方式都可以。 *你*說功能的方式是不太可讀的,但這可能完全是因爲*你*是如此習慣於命令式的構造,它看起來很奇怪或不那麼表達。一旦你習慣了功能結構*,這兩種方法都是正確和清晰的。另一方面,沒有理由用一些清晰可讀的功能等價結構來替換一個清晰可讀的命令式結構...... –

3

沒有理由改變你的實現。有沒有辦法做你想要的東西在java 8與可選沒有一個if,同時尊重不使用'地圖'的副作用的想法。

我的意思是,你可以有

public void check(String name) { 
    Optional<String> nameOpt = Optional.ofNullable(name); 
    nameOpt.ifPresent(n -> doSomething(n)); 
    if (!nameOpt.isPresent()) { 
     doMore(); 
    } 
} 

,但有沒有意義。 here你有一篇好文章,可選試圖解決的問題(以及爲什麼要使用它):主要用於返回類型。其他的東西只是過度使用它。

2

您可以通過利用Java 8 Optional.map()Optional.orElseGet()方法避免if聲明。檢查下面的例子:

import java.util.Optional; 
import java.util.function.Consumer; 

final class OptionalTestMain { 

    public static void main(String[] args) { 
     check("test", str -> { 
      System.out.println("Yay, string is not null!"); 
      System.out.println("It's: " + str); 
     },() -> { 
      System.out.println("Crap, string is a null..."); 
      System.out.println("There is nothing for me to do."); 
     }); 

     check(null, str -> { 
      System.out.println("Yay, string is not null!"); 
      System.out.println("It's: " + str); 
     },() -> { 
      System.out.println("Crap, string is a null..."); 
      System.out.println("There is nothing for me to do."); 
     }); 
    } 

    static void check(String str, Consumer<String> ifPresent, Runnable ifNotPresent) { 
     Optional.ofNullable(str) 
       .map(s -> { ifPresent.accept(s); return s; }) 
       .orElseGet(() -> { ifNotPresent.run(); return null; }); 
    } 
} 

它會產生以下輸出:

Yay, string is not null! 
It's: test 
Crap, string is a null... 
There is nothing for me to do. 

方法check預計3個參數:

  • 一個字符串(它可以是null
  • 一個Consumer拉姆達表達式用這個值做一些事情,不會改變的輸入值。
  • a Runnable沒有參數的lambda在輸入時做某事Stringnull

當然,你可以很容易地修改下面的方法,然後利用Optional類的全部潛力,如:

static String checkAndReturn(String str, Function<String, String> ifPresent, Supplier<String> ifNotPresent) { 
    return Optional.ofNullable(str) 
      .map(ifPresent) 
      .orElseGet(ifNotPresent); 
} 

然後:

System.out.println(checkAndReturn("test", String::toUpperCase,() -> "no value")); 
System.out.println(checkAndReturn(null, String::toUpperCase,() -> "no value")); 

會產生以下的輸出:

TEST 
no value 

我希望它有幫助。