Що стосується повноти, то справді "кілька змінних" справді можливо, хоч і зовсім не елегантно. Наприклад, для змінних o
, p
і q
:
Optional.ofNullable( o ).orElseGet(()-> Optional.ofNullable( p ).orElseGet(()-> q ) )
Будь-ласка, зверніть увагу на використання orElseGet()
участі у справі, яка o
, p
і q
не є змінними, а виразами або дорогими, або з небажаними побічними ефектами.
У самому загальному випадку 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
Це може генерувати вирази надмірно довго. Однак, якщо ми намагаємось перейти у світ без null
, то v[i]
, швидше за все, вже типу Optional<String>
, на відміну від просто String
. В цьому випадку,
result= o.orElse(p.orElse(q.get())) ;
або у разі виразів:
result= o.orElseGet(()-> p.orElseGet(()-> q.get() ) ) ;
Крім того, якщо ви також перехід до функціонально-декларативним стилю o
, p
і q
має бути типу , Supplier<String>
як в:
Supplier<String> q= ()-> q-expr ;
Supplier<String> p= ()-> Optional.ofNullable(p-expr).orElseGet( q ) ;
Supplier<String> o= ()-> Optional.ofNullable(o-expr).orElseGet( p ) ;
І тоді все coalesce
зводиться просто до o.get()
.
Для більш конкретного прикладу:
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()
і ageFromInput()
вже повернувся б Optional<Integer>
, природно.
І тоді coalesce
стає effectiveAge.get()
або просто, effectiveAge
якщо ми задоволені Supplier<Integer>
.
IMHO, з Java 8 ми бачимо все більше і більше структурованого коду, як це, оскільки він є надзвичайно зрозумілим і ефективним водночас, особливо у більш складних випадках.
Я пропускаю клас, Lazy<T>
який викликає Supplier<T>
лише один раз, але ліниво, а також послідовність у визначенні Optional<T>
(тобто Optional<T>
- Optional<T>
операторів чи навіть Supplier<Optional<T>>
).