The full picture
// ❌ 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 bareget().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.