Apenas para completar, o caso "várias variáveis" é realmente possível, embora nem um pouco elegante. Por exemplo, para as variáveis o
, p
e q
:
Optional.ofNullable( o ).orElseGet(()-> Optional.ofNullable( p ).orElseGet(()-> q ) )
Por favor, note o uso de orElseGet()
assistir ao caso que o
, p
eq
não são variáveis, mas expressões caro ou com efeitos colaterais indesejáveis.
No caso mais geral 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
Isso pode gerar expressões excessivamente longas. No entanto, se estamos tentando mudar para um mundo sem null
, v[i]
provavelmente já somos do tipo Optional<String>
, e não simplesmente String
. Nesse caso,
result= o.orElse(p.orElse(q.get())) ;
ou no caso de expressões:
result= o.orElseGet(()-> p.orElseGet(()-> q.get() ) ) ;
Além disso, se você também está se movendo para um estilo funcional-declarativa, o
, p
, e q
deve ser do tipo Supplier<String>
como em:
Supplier<String> q= ()-> q-expr ;
Supplier<String> p= ()-> Optional.ofNullable(p-expr).orElseGet( q ) ;
Supplier<String> o= ()-> Optional.ofNullable(o-expr).orElseGet( p ) ;
E então o todo se coalesce
reduz simplesmente a o.get()
.
Para um exemplo mais concreto:
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()
E ageFromInput()
já ia voltar Optional<Integer>
, naturalmente.
E então o coalesce
torna - se effectiveAge.get()
ou simplesmente effectiveAge
se estamos felizes com a Supplier<Integer>
.
IMHO, com o Java 8, veremos cada vez mais código estruturado dessa maneira, pois é extremamente auto-explicativo e eficiente ao mesmo tempo, especialmente em casos mais complexos.
Sinto falta de uma classe Lazy<T>
que invoca Supplier<T>
apenas uma vez, mas preguiçosamente, além da consistência na definição de Optional<T>
(ie Optional<T>
- Optional<T>
operadores, ou mesmo Supplier<Optional<T>>
).