Interview Prep Zoneby CuriouserLabs

Question 3 of 5 · senior level

What is Optional for — and what are the abuse patterns you'd flag in code review?

🎤 Say this first

Optional is a return-type protocol: it forces callers of query methods to confront absence, replacing null-or-NPE roulette. It is not a general null-replacement: don't use it for fields, method parameters, or collections (empty collection ≥ Optional of collection), and don't call get() without checking. Prefer functional composition — map, flatMap, filter, orElseGet, orElseThrow — over isPresent()/get() pairs, which are just null-checks in costume.

The full picture

Review comments in code form
// ❌ Optional parameter — pushes ceremony onto every caller
void render(Optional<User> user) { … }
// ✅ overload or @Nullable parameter, Optional stays on returns

// ❌ field of type Optional — not serializable, adds a box per field
private Optional<String> nickname;
// ✅ nullable field + Optional-returning getter if needed

// ❌ the costume null-check
if (opt.isPresent()) { use(opt.get()); }
// ✅ composition
opt.map(this::use).orElseGet(this::fallback);

// ❌ orElse with an expensive expression — ALWAYS evaluated
config.orElse(loadDefaultsFromDisk());     // runs even when present!
config.orElseGet(this::loadDefaultsFromDisk); // lazy ✅
  • orElseThrow() (no-arg, Java 10) is the intention-revealing replacement for bare get().
  • Optional.stream() (Java 9) makes filter-present-and-unwrap clean in pipelines: ids.map(repo::find).flatMap(Optional::stream).
  • Repository APIs returning Optional<T> vs throwing: Optional for 'absence is normal', exception for 'absence is a bug' — pick per use-case, deliberately.

🔄 Likely follow-up questions

  • Why is Optional not Serializable, and what does that imply for entities?
  • How does Optional interact with JPA/Hibernate attribute types?
  • Kotlin nullable types vs Optional — trade-offs at an API boundary?