2014-06-15 7 views
36

Ich versuche, die ifPresent() Methode der Optional API in Java 8.Gemäßer Gebrauch von Optional.ifPresent()

Ich habe einfache Logik zu verstehen:

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

Aber dies führt zu einem Kompilierungsfehler :

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

natürlich kann ich so etwas tun:

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

Aber das ist genau wie eine überladene null überprüfen.

Wenn ich ändern Sie den Code in dem:

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

Der Code wird immer dreckiger, was ich gehe zurück zu dem alten null Check denken läßt.

Irgendwelche Ideen?

Antwort

60

Optional<User>.ifPresent() dauert ein Consumer<? super User> als Argument. Du gibst einen Ausdruck, dessen Typ ungültig ist. Das kompiliert also nicht.

A Consumer soll als Lambda-Ausdruck umgesetzt werden:

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

Oder noch einfacher, ein Verfahren Referenzen:

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

Dies ist im Grunde das gleiche wie

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

Die Idee ist, dass der Methodenaufruf doSomethingWithUser() nur ausgeführt wird, wenn der Benutzer ist anwesend. Ihr Code führt den Methodenaufruf direkt aus und versucht, das Voir-Ergebnis an ifPresent() zu übergeben.

+0

Dieser Code wird überladen .. ein Null-Check wird viel sauberer sein. denkst du nicht besonders, dass DoSomethingWithUser keine statische Methode ist? – rayman

+0

Welcher Code?Die eine, die Sie verwenden sollten, ist die zweite, die die Instanz (d. H. Nicht statische) Methode doSomethingWithUser() aufruft. Ich sehe nicht, wie es überladen ist. Der letzte Code ist dazu da, Ihnen das Äquivalent des Lambda in einer vor-Lambda-Welt zu erklären. Benutze es nicht. –

+0

Ahh ich verstehe dich. Wenn ich nicht in einer Lambda-Welt bin, gibt es keine Verwendung für die Option api eh – rayman

2

Sie müssen es so verwenden:

user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser); 

Methode ifPresent()Consumer Objekt als paremeter zu erhalten und (von JavaDoc): „Wenn ein Wert vorhanden ist, die angegebene Verbraucher mit dem Wert aufzurufen.“ Wert ist Ihre Variable user.

+1

Aber doSomethingWithUser ist weder eine statische Methode noch eine Klasse. – rayman

+0

@rayman Ok, wenn nicht statisch können Sie das folgendermaßen tun: 'user.ifPresent (new ClassNameWhereMethodIs() :: doSomethingWithUser);' –

+2

@AleksandrPodkutin Sie sollten keine neue Instanz der Klasse erstellen, nur um eine Methode auszuführen, von Das OP hört sich an, als ob die Methode in der gleichen Klasse ist, wie sie aufgerufen wird. Daher sollte er 'user.ifPresent (this :: doSomethingWithUser);' verwenden – Marv

5

Neben @ JBNizet Antwort, mein allgemeiner Anwendungsfall für ifPresent ist .isPresent() und .get() zu kombinieren:

Alte Art und Weise:

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

Neuer Weg:

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

Dies, zu mir, ist intuitiver.

Verwandte Themen