The Optional type was introduced in Java 8 as a way to indicate that a method may return a value.
In other words, there is a chance the method returns "no value" at all.
Given an object of type Employee, an Optional object can be created using the static of method:
Employee employee = new Employee();
Optional<Employee> optionalEmployee = Optional.of(employee);
If the employee may be not present, the static ofNullable method must be used:
Employee nullableEmployee = new Employee();
Optional<Employee> nullableEmployee = Optional.ofNullable(employee);
optionalEmployee
and nullableEmployee
both are wrappers of an Employee
object.
If a value is present, the isPresent method returns true and the get method returns the value.
Employee employee = new Employee("Tim", 45);
Optional<Employee> optionalEmployee = Optional.ofNullable(employee);
boolean isThereAnEmployee = optionalEmployee.isPresent(); // true
Employee employee = optionalEmployee.get();
In order to throw an exception when the value is not present, the orElseThrow method must be used.
public Optional<Employee> getEmployee(String name) {
// Assume that getEmployeeByName returns an Optional<Employee>
return getEmployeeByName(name)
.orElseThrow(() -> new IllegalArgumentException("Employee not found"));
}
If a default value must be returned, the orElse method can be used.
public Optional<Employee> getEmployee(String name) {
// Assume that getEmployeeByName returns an Optional<Employee>
return getEmployeeByName(name)
.orElse(new Employee("Daniel"));
}
Other commonly used method is ifPresentOrElse, which is used to handle both cases with the same method: the case where the value is present and the case where the value is empty.
public Optional<Employee> getEmployee(String name) {
// Assume that getEmployeeByName returns an Optional<Employee>
return getEmployeeByName(name)
.ifPresentOrElse(
employee -> System.out.println(employee.getName()),
() -> System.out.println("Employee not found")
);
}
Provided all the invoked methods return Optional objects, many methods can be chained without having to worry about null checking:
public Optional<Integer> getEmployeeAge(String name) {
Optional<Employee> optionalEmployee = getEmployeeByName(name);
return getEmployeeByName(name)
.map(employee -> employee.getAge())
.orElse("No employee found");
}