Chỉ để hoàn thiện, trường hợp "một vài biến" thực sự có thể, mặc dù không thanh lịch chút nào. Ví dụ, đối với các biến o
, p
và q
:
Optional.ofNullable( o ).orElseGet(()-> Optional.ofNullable( p ).orElseGet(()-> q ) )
Xin lưu ý việc sử dụng các orElseGet()
tham dự vào các trường hợp đó o
, p
vàq
không biến nhưng biểu thức hoặc đắt tiền hoặc với mong muốn tác dụng phụ.
Trong trường hợp chung nhất 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
Điều này có thể tạo ra các biểu thức quá dài. Tuy nhiên, nếu chúng ta đang cố gắng di chuyển đến một thế giới mà không có null
, thì v[i]
có lẽ hầu hết đã thuộc loại Optional<String>
, trái ngược với đơn giản String
. Trong trường hợp này,
result= o.orElse(p.orElse(q.get())) ;
hoặc trong trường hợp biểu thức:
result= o.orElseGet(()-> p.orElseGet(()-> q.get() ) ) ;
Hơn nữa, nếu bạn cũng đang di chuyển đến một phong cách chức năng-declarative, o
, p
, và q
nên loại Supplier<String>
như trong:
Supplier<String> q= ()-> q-expr ;
Supplier<String> p= ()-> Optional.ofNullable(p-expr).orElseGet( q ) ;
Supplier<String> o= ()-> Optional.ofNullable(o-expr).orElseGet( p ) ;
Và sau đó toàn bộ coalesce
giảm đơn giản để o.get()
.
Đối với một ví dụ cụ thể hơn:
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()
và ageFromInput()
sẽ trở lại Optional<Integer>
, một cách tự nhiên.
Và sau đó coalesce
trở thành effectiveAge.get()
hoặc đơn giản effectiveAge
nếu chúng ta hài lòng với a Supplier<Integer>
.
IMHO, với Java 8, chúng ta sẽ thấy ngày càng nhiều mã được cấu trúc như thế này, vì nó cực kỳ tự giải thích và hiệu quả cùng một lúc, đặc biệt là trong các trường hợp phức tạp hơn.
Tôi nhớ một lớp Lazy<T>
chỉ gọi một lần Supplier<T>
duy nhất, nhưng uể oải, cũng như sự nhất quán trong định nghĩa của Optional<T>
(tức là Optional<T>
- Optional<T>
toán tử, hoặc thậm chí Supplier<Optional<T>>
).