Nur der Vollständigkeit halber ist der Fall "mehrere Variablen" zwar möglich, aber überhaupt nicht elegant. Zum Beispiel für Variablen o
, p
und q
:
Optional.ofNullable( o ).orElseGet(()-> Optional.ofNullable( p ).orElseGet(()-> q ) )
Bitte beachten Sie, dass Sie sich orElseGet()
um den Fall kümmern o
müssen p
, dass q
es sich nicht um Variablen handelt, sondern um Ausdrücke, die entweder teuer sind oder unerwünschte Nebenwirkungen haben.
Im allgemeinsten Fall coalesce(e[1],e[2],e[3],...,e[N])
coalesce-expression(i) == e[i] when i = N
coalesce-expression(i) == Optional.ofNullable( e[i] ).orElseGet(()-> coalesce-expression(i+1) ) when i < N
Dies kann zu lange Ausdrücke erzeugen. Wenn wir jedoch versuchen, uns in eine Welt ohne zu bewegen null
, dann v[i]
sind wir höchstwahrscheinlich schon vom Typ Optional<String>
, im Gegensatz zu einfach String
. In diesem Fall,
result= o.orElse(p.orElse(q.get())) ;
oder im Fall von Ausdrücken:
result= o.orElseGet(()-> p.orElseGet(()-> q.get() ) ) ;
Wenn Sie darüber hinaus auch zu einem funktionellen-deklarativem Stil bewegen, o
, p
, und q
sollte vom Typ sein , Supplier<String>
wie in:
Supplier<String> q= ()-> q-expr ;
Supplier<String> p= ()-> Optional.ofNullable(p-expr).orElseGet( q ) ;
Supplier<String> o= ()-> Optional.ofNullable(o-expr).orElseGet( p ) ;
Und dann coalesce
reduziert sich das Ganze einfach auf o.get()
.
Für ein konkreteres Beispiel:
Supplier<Integer> hardcodedDefaultAge= ()-> 99 ;
Supplier<Integer> defaultAge= ()-> defaultAgeFromDatabase().orElseGet( hardcodedDefaultAge ) ;
Supplier<Integer> ageInStore= ()-> ageFromDatabase(memberId).orElseGet( defaultAge ) ;
Supplier<Integer> effectiveAge= ()-> ageFromInput().orElseGet( ageInStore ) ;
defaultAgeFromDatabase()
, ageFromDatabase()
Und ageFromInput()
würde schon zurückkehren Optional<Integer>
, natürlich.
Und dann coalesce
wird das effectiveAge.get()
oder einfach effectiveAge
wenn wir mit einem zufrieden sind Supplier<Integer>
.
IMHO, mit Java 8 werden wir immer mehr Code sehen, der so strukturiert ist, da er extrem selbsterklärend und gleichzeitig effizient ist, insbesondere in komplexeren Fällen.
Ich vermisse eine Klasse Lazy<T>
, die Supplier<T>
nur einmal, aber träge, sowie Konsistenz in der Definition von Optional<T>
(dh Optional<T>
- Optional<T>
Operatoren oder sogar Supplier<Optional<T>>
) aufruft .