Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java Optional: eager defaults and lazy suppliers

Last updated: 29 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

Optional.orElse evaluates its argument before the call, while orElseGet invokes its supplier only when the Optional is empty.

Download Java source kit

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

Java
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

Output
cached
1
cached
1
archive
2

Costs 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.

java
optional-evaluation
Storage details