2014-06-15 12 views
36

Próbuję zrozumieć sposobu Optional API ifPresent() w Javie 8.Prawidłowe wykorzystanie Optional.ifPresent()

mam prostą logikę:

Optional<User> user=... 
user.ifPresent(doSomethingWithUser(user.get())); 

Ale to powoduje błąd kompilacji :

ifPresent(java.util.functionError:(186, 74) java: 'void' type not allowed here) 

oczywiście mogę zrobić coś takiego:

if(user.isPresent()) 
{ 
    doSomethingWithUser(user.get()); 
} 

Ale to jest dokładnie tak, jak zagracone sprawdzanie null.

Gdybym zmienić kod na to:

user.ifPresent(new Consumer<User>() { 
      @Override public void accept(User user) { 
       doSomethingWithUser(user.get()); 
      } 
     }); 

Kod jest coraz brudniejsze, co sprawia, że ​​myślę o powrocie do starego null czeku.

Wszelkie pomysły?

Odpowiedz

60

Optional<User>.ifPresent() przyjmuje argument jako Consumer<? super User>. Przekazujesz mu wyrażenie, którego typ jest nieważny. Więc to się nie kompiluje.

Konsument ma być realizowany jako wyrażenie lambda:

Optional<User> user = ... 
user.ifPresent(theUser -> doSomethingWithUser(theUser)); 

Albo jeszcze prościej, wykorzystując odniesienia metoda:

Optional<User> user = ... 
user.ifPresent(this::doSomethingWithUser); 

Jest to w zasadzie to samo, co

Optional<User> user = ... 
user.ifPresent(new Consumer<User>() { 
    @Override 
    public void accept(User theUser) { 
     doSomethingWithUser(theUser); 
    } 
}); 

Chodzi o to, że wywołanie metody doSomethingWithUser() zostanie wykonane tylko wtedy, gdy użytkownik jest obecny. Twój kod wykonuje wywołanie metody bezpośrednio i próbuje przekazać swój wynik voir do ifPresent().

+0

Ten kod się zagraca. Sprawdzenie wartości zerowej będzie znacznie czystsze. nie sądzisz? s specjalnie, że doSomethingWithUser nie jest metodą statyczną. – rayman

+0

Który kod?Ten, którego powinieneś użyć, to drugi, który wywołuje instancję (tzn. Niestatyczną) metodę doSomethingWithUser(). Nie rozumiem, jak jest zagracony. Ostatni kod zawiera wyjaśnienie ekwiwalentu lambda w świecie przed lambdą. Nie używaj go. –

+0

Ahh rozumiem cię. Jeśli nie jestem w świecie lambda, nie ma możliwości używania Opcjonalnego api eh – rayman

2

trzeba używać go tak:

user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser); 

Metoda ifPresent() dostać Consumer obiekt jako paremeter i (od JavaDoc): „Jeżeli wartość nie jest obecny, wywołać określony konsumentowi wartości.” Oceń swoją zmienną user.

+1

Ale doSomethingWithUser nie jest metodą statyczną ani klasą. – rayman

+0

@rayman Ok, jeśli nie jest statyczna, możesz zrobić tak: 'user.ifPresent (new ClassNameWhereMethodIs() :: doSomethingWithUser);' –

+2

@AleksandrPodkutin nie powinieneś tworzyć nowej instancji klasy tylko po to, aby uruchomić jedną metodę, od OP brzmi, jakby metoda była w tej samej klasie, z której jest wywoływana, więc powinien użyć 'user.ifPresent (this :: doSomethingWithUser);' – Marv

5

Poza użytkownika @ JBNizet odpowiedź, mój ogólny przypadek użycia dla ifPresent jest łączenie .isPresent() i .get():

stary sposób:

Optional opt = getIntOptional(); 
if(opt.isPresent()) { 
    Integer value = opt.get(); 
    // do something with value 
} 

Nowy sposób:

Optional opt = getIntOptional(); 
opt.ifPresent(value -> { 
    // do something with value 
}) 

to, dla mnie jest bardziej intuicyjny.