Java 8 Optional Examples
Optional<T>
is useful in avoiding the unchecked NullPointerException
as it provides a type-safe object that may or may not
contain a value, and so it is up to the calling code to specifically check if
there is a value or not. The idea is to force us to think about what to do
when we’re writing code, rather than accidentally hitting a NullPointerException
if a function returns null
.
For example, Optional<T>
is used a lot with the Stream
API to force us to
thoughtfully handle the situation where there might be an empty stream.
Basic Usage
import xyz.byexample.Person;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class OptionalValues {
private static List<Person> people = new ArrayList<>();
public static void main(String[] args) {
Optional<Person> maybePerson = getPersonByName("Bill");
if (maybePerson.isPresent()) {
System.out.println("Person was found");
} else {
System.out.println("Person was not found");
}
}
public static Optional<Person> getPersonByName(String name) {
for (Person p : people) {
if (p.getName().equals(name)) {
return Optional.of(p);
}
}
return Optional.empty();
}
}
Output
Person was not found
If you are using a collection that supports streams, this is even easier since
functions like findFirst()
and findAny()
already return an Optional<T>
while keeping your code shorter and clearer - here we can change the implementation
of getPersonByName
to use streams and findFirst
:
public static void main(String[] args) {
Optional<Person> maybePerson = getPersonByName("Bill");
if (maybePerson.isPresent()) {
System.out.println("Person was found");
} else {
System.out.println("Person was not found");
}
}
public static Optional<Person> getPersonByName(String name) {
// Much shorter implementation of getPersonByName
return people.stream().filter(p -> name.equals(p.getName())).findFirst();
}