Pour être complet, le cas «plusieurs variables» est en effet possible, mais pas du tout élégant. Par exemple, pour les variables o, pet q:
Optional.ofNullable( o ).orElseGet(()-> Optional.ofNullable( p ).orElseGet(()-> q ) )
Veuillez noter qu'il est utile de orElseGet()s'occuper du cas qui o, pet qne sont pas des variables mais des expressions coûteuses ou avec des effets secondaires indésirables.
Dans le cas le plus général 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
Cela peut générer des expressions excessivement longues. Cependant, si nous essayons de passer à un monde sans null, alors v[i]sont très probablement déjà de typeOptional<String> , par opposition à simplement String. Dans ce cas,
result= o.orElse(p.orElse(q.get())) ;
ou dans le cas d'expressions:
result= o.orElseGet(()-> p.orElseGet(()-> q.get() ) ) ;
De plus, si vous prépare également à un style fonctionnel déclarative, o, pet qdevrait être de typeSupplier<String> comme dans:
Supplier<String> q= ()-> q-expr ;
Supplier<String> p= ()-> Optional.ofNullable(p-expr).orElseGet( q ) ;
Supplier<String> o= ()-> Optional.ofNullable(o-expr).orElseGet( p ) ;
Et puis le tout coalesce réduit simplement à o.get().
Pour un exemple plus concret:
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() et ageFromInput()reviendraient déjà Optional<Integer>, naturellement.
Et puis le coalescedevienteffectiveAge.get() ou simplement effectiveAgesi nous sommes satisfaits d'un Supplier<Integer>.
IMHO, avec Java 8, nous verrons de plus en plus de code structuré comme celui-ci, car il est extrêmement auto-explicatif et efficace en même temps, en particulier dans les cas plus complexes.
Je manque une classe Lazy<T>qui n'invoque Supplier<T>qu'une seule fois, mais paresseusement, ainsi que la cohérence dans la définition de Optional<T>(ie Optional<T>- Optional<T>opérateurs, ou même Supplier<Optional<T>>).