Optional.orElse evaluates its argument before the call, while orElseGet invokes its supplier only when the Optional is empty.
Java Optional: eager defaults and lazy suppliers
The complete program targets Java 8. Compile it as one source file; its output is checked against the lesson.
An unused default can still do work
A receipt lookup already found a cached value. Passing a fallback method to orElse does not postpone that method; Java evaluates the method argument even though Optional later returns the cached value. The fallback could allocate a document, query a database or fail.
The counter in this program records actual fallback calls. It is intentionally local and deterministic. orElseGet avoids the call on a present value, but writing a supplier that closes over an already-computed fallback will not undo the earlier computation.
Absence is a domain choice
A supplier can return null, so the return value of orElseGet is not automatically non-null. If absence is an error, orElseThrow can express that boundary directly. Avoid using Optional merely to hide a missing value that the caller must handle explicitly.
The fixture uses a single thread. Adding suppliers with mutable shared counters needs synchronization, and deferring a remote lookup still needs a timeout and failure policy. Lazy evaluation controls when work starts; it does not make the work safe or inexpensive.
Working program
import java.util.Optional;
public class ReceiptFallbackCalls {
static int calls;
static String loadArchive() { calls++; return "archive"; }
public static void main(String[] args) {
Optional<String> receipt = Optional.of("cached");
System.out.println(receipt.orElse(loadArchive()));
System.out.println(calls);
System.out.println(receipt.orElseGet(ReceiptFallbackCalls::loadArchive));
System.out.println(calls);
System.out.println(Optional.<String>empty().orElseGet(ReceiptFallbackCalls::loadArchive));
System.out.println(calls);
}
}Output
cached
1
cached
1
archive
2Costs and boundaries
Optional selection itself is bounded work. The fallback cost depends on the operation supplied. Captured state can keep objects reachable longer than expected; a supplier is not a free replacement for designing the lookup lifecycle.
Common Mistakes
- Do not assume an orElse argument is lazy.
- Do not compute the fallback before creating its supplier.
- Handle exceptions from the supplier at the intended boundary.
Read next
Java Optional: absence without hidden failure, Java lambdas: function contracts and captured state, Object provider.
