Optional
Making absence explicit — of vs ofNullable, why get() is dangerous, ifPresent, orElse vs orElseGet, orElseThrow, and map/filter/flatMap on Optional.
#Introduction
If there is one Java 8 feature that interviewers love after Streams, it's Optional.
#Why Was Optional Introduced?
Before Java 8:
User user = repository.findById(id);
if (user != null) {
System.out.println(user.getName());
}The problem: NullPointerException. Millions of production bugs happen because of null. Java 8 introduced Optional to make the absence of a value explicit.
Think of it as a box:
#Creating an Optional
Optional.of()
String name = "John";
Optional<String> optional = Optional.of(name);If name is null, Optional.of(null) throws NullPointerException. Use it only when you're sure the value isn't null.
Optional.ofNullable()
String name = null;
Optional<String> optional = Optional.ofNullable(name);
System.out.println(optional);Optional.emptyThis is the method you'll use most often.
Optional.empty()
Optional<String> optional = Optional.empty();An empty Optional.
#Reading the Value
isPresent()
Optional<String> name = Optional.of("John");
if (name.isPresent()) {
System.out.println(name.get());
}JohnWhy get() is Dangerous
Optional<String> name = Optional.empty();
name.get();NoSuchElementException: No value presentifPresent()
Instead of:
if (optional.isPresent()) {
System.out.println(optional.get());
}use:
optional.ifPresent(System.out::println);Cleaner and safer.
#Default Values
orElse()
Return a default value.
Optional<String> name = Optional.empty();
String result = name.orElse("Guest");
System.out.println(result);GuestorElseGet()
Looks similar, but is different:
String result = optional.orElseGet(() -> "Guest");Why? Because the supplier is executed only if needed.
#orElse() vs orElseGet() — Proof
A classic interview question. Let's prove the difference.
public static String expensiveMethod() {
System.out.println("Executing...");
return "Guest";
}Case 1 — orElse():
Optional<String> optional = Optional.of("John");
System.out.println(optional.orElse(expensiveMethod()));Executing...
JohnWait… why did expensiveMethod() execute? Because orElse() evaluates its argument before it checks whether the Optional contains a value — it's an ordinary method argument.
Case 2 — orElseGet():
Optional<String> optional = Optional.of("John");
System.out.println(optional.orElseGet(() -> expensiveMethod()));JohnNo "Executing...". The supplier wasn't called because the value was already present.
The Rule
| Use orElse() for | Use orElseGet() for |
|---|---|
| Constants | Expensive database calls |
Simple default values, e.g. .orElse("Guest") | API calls |
| Object creation | |
| Complex logic |
#orElseThrow()
Suppose a user must exist:
User user = repository.findById(id)
.orElseThrow();If not found → NoSuchElementException.
With a custom exception:
User user = repository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"));Very common in Spring Boot services.
#Transforming an Optional
map()
Optional<Employee> employee = repository.findById(1);Need the employee name. Instead of:
if (employee.isPresent()) {
return employee.get().getName();
}use:
String name = employee
.map(Employee::getName)
.orElse("Unknown");Beautiful.
filter()
Optional<Employee> employee = repository.findById(1);
employee
.filter(e -> e.getSalary() > 50000)
.ifPresent(System.out::println);flatMap()
Suppose Optional<User> where User.getAddress() returns Optional<Address>.
Optional<Address> address = user.flatMap(User::getAddress);#Real Spring Boot Example
public UserDTO getUser(Long id) {
return repository.findById(id)
.map(UserMapper::toDto)
.orElseThrow(() -> new UserNotFoundException(id));
}This is production-quality code.
#Interview Questions
Q1Difference between Optional.of() and Optional.ofNullable()?
of()never acceptsnull(throwsNullPointerException).ofNullable()acceptsnulland returnsOptional.empty().
Q2Difference between orElse() and orElseGet()?
orElse()eagerly evaluates its argument.orElseGet()lazily invokes the supplier only when needed.
Q3Why avoid Optional.get()?
Because it throws NoSuchElementException when the Optional is empty.
Q4Can an Optional be null?
Technically yes, but you should never make an Optional variable itself null. An empty Optional already represents "no value."
Q5Where is Optional used most?
- Repository methods like
findById() - Service-layer transformations
- Null-safe chaining
- Stream terminal operations like
findFirst(),max(),min()
#Practice Problems
- Create an Optional from a nullable string.
- Print the value using
ifPresent(). - Return
"Unknown"if the value is absent. - Use
orElseGet()with an expensive method. - Throw a custom exception with
orElseThrow(). - Convert
Optional<Employee>toOptional<String>usingmap(). - Filter employees whose salary is greater than 50,000.
- Chain
map()andfilter()together. - Use
flatMap()with nested Optionals. - Rewrite legacy null checks using
Optional.
#Chapter Summary
Optional.of(),ofNullable(),empty()- Why
get()is dangerous; preferifPresent() orElse()(eager) vsorElseGet()(lazy)orElseThrow()with a custom exceptionmap(),filter(),flatMap()on Optional- The Spring Boot
findById().map().orElseThrow()pattern