Java Optional is a class that represents a value that may or may not be present. It is used to avoid NullPointerExceptions when dealing with nullable values.
Optional
is a class introduced to handle the absence of a value in a more elegant and safe way. It is designed to avoid null pointer exceptions and make it clear when a value may be absent. An Optional
object can either contain a non-null value or represent that no value is present.
Before Java 8, when a method could return a null
value, developers had to explicitly check for null before performing any operations on the returned value. This often led to cluttered and error-prone code. With Optional
, you can avoid explicit null checks and handle the absence of values in a more functional and streamlined manner.
The Optional
class provides several methods to interact with and manipulate the contained value, such as get()
, isPresent()
, orElse()
, orElseGet()
, orElseThrow()
, and more.
Here’s a simple example to demonstrate the use of Optional
:
import java.util.Optional; public class OptionalExample { public static void main(String[] args) { String name = "John"; // Change this to null to see the difference // Creating an Optional object from the value Optional<String> optionalName = Optional.ofNullable(name); // Checking if a value is present if (optionalName.isPresent()) { System.out.println("Name: " + optionalName.get()); } else { System.out.println("Name is not present."); } // Using orElse to provide a default value if the value is absent String defaultName = optionalName.orElse("Unknown"); System.out.println("Default Name: " + defaultName); // Using orElseGet to provide a default value using a supplier if the value is absent String otherDefaultName = optionalName.orElseGet(() -> "Anonymous"); System.out.println("Other Default Name: " + otherDefaultName); } }
Output when name = "John"
:
Name: John Default Name: John Other Default Name: John
Output when name = null
:
Name is not present. Default Name: Unknown Other Default Name: Anonymous
In this example, we create an Optional
object using the static ofNullable()
method. If the value is present, we can retrieve it using the get()
method. However, it is advisable to use the isPresent()
method before calling get()
to avoid a NoSuchElementException
. Alternatively, you can use the orElse()
method to provide a default value if the Optional
object is empty.
The Optional
class encourages better code design by making it explicit when a value may be absent and providing clear methods for handling both present and absent cases.
It’s essential to use Optional
wisely and not overuse it. It is best suited for method return types and fields that might be absent. Avoid using Optional
as a replacement for traditional null checks within method bodies.
Here are some of the benefits of using Java Optional:
isPresent()
The Optional class provides the isPresent() method, which is used to check whether an Optional object contains a non–null value or is empty (contains a null value). The isPresent() method returns a boolean value indicating whether the Optional object holds a value.
static void isPresent() { System.out.println("isPresent..."); String firstName = faker.name().firstName(); String lastName = faker.name().lastName(); String email = (firstName + lastName).toLowerCase() + "@gmail.com"; User user = User.builder().firstName(firstName).lastName(lastName).email(email).phoneNumber(faker.phoneNumber().cellPhone()).build(); System.out.println("User: " + user.toString()); Optional<User> optUser = Optional.ofNullable(user); // Checking if the Optional object contains a value if (optUser.isPresent()) { System.out.println("User is present: " + optUser.get()); } else { System.out.println("User is not present."); } System.out.println("isPresent done!"); }
The output
isPresent... User: User(id=0, firstName=Natalie, lastName=Braun, email=nataliebraun@gmail.com, phoneNumber=975.490.2241) User is present: User(id=0, firstName=Natalie, lastName=Braun, email=nataliebraun@gmail.com, phoneNumber=975.490.2241) isPresent done!
ifPresentOrElse()
The Optional
class introduced the ifPresentOrElse()
method. This method provides a concise way to perform an action if the Optional
object contains a value, and an alternative action if the Optional
object is empty.
static void ifPresentOrElse() { System.out.println("ifPresentOrElse..."); String firstName = faker.name().firstName(); String lastName = faker.name().lastName(); String email = (firstName + lastName).toLowerCase() + "@gmail.com"; User user = User.builder().firstName(firstName).lastName(lastName).email(email).phoneNumber(faker.phoneNumber().cellPhone()).build(); System.out.println("User: " + user.toString()); Optional<User> optUser = Optional.ofNullable(user); optUser.ifPresentOrElse(u -> { System.out.println("user is present"); System.out.println("User: " + u.toString()); }, () -> { System.out.println("else"); }); user = null; optUser = Optional.ofNullable(user); optUser.ifPresentOrElse(u -> { System.out.println("user is present"); }, () -> { System.out.println("user is null"); }); System.out.println("ifPresentOrElse done!"); }
ofElse()
static void orElse() { System.out.println("orElse..."); String firstName = faker.name().firstName(); String lastName = faker.name().lastName(); String email = (firstName + lastName).toLowerCase() + "@gmail.com"; User user = User.builder().firstName(firstName).lastName(lastName).email(email).phoneNumber(faker.phoneNumber().cellPhone()).build(); System.out.println("User: " + user.toString()); Optional<User> optUser = Optional.ofNullable(user); User u = optUser.orElse(User.builder().firstName("Test").build()); System.out.println("User firstName: " + u.getFirstName()); user = null; optUser = Optional.ofNullable(user); u = optUser.orElse(User.builder().firstName("Test").build()); System.out.println("User firstName: " + u.getFirstName()); System.out.println("orElse done!"); }
filter()
The Optional class provides the filter() method, which is used to conditionally process the value contained within the Optional. The filter() method checks if the Optional contains a value that matches a given predicate (a condition), and if so, it returns the same Optional object. If the Optional is empty (contains a null value) or the predicate evaluates to false for the value, the filter() method returns an empty Optional.
static void filter() { System.out.println("filter..."); String firstName = faker.name().firstName(); String lastName = faker.name().lastName(); String email = (firstName + lastName).toLowerCase() + "@gmail.com"; User user = User.builder().firstName(firstName).lastName(lastName).email(email).phoneNumber(faker.phoneNumber().cellPhone()).build(); System.out.println("User: " + user.toString()); user = null; Optional<User> optUser = Optional.ofNullable(user); optUser = optUser.filter(u -> { System.out.println("running filter if value is not null"); return u.getFirstName().length() > 0; }); optUser.ifPresent(u -> { System.out.println("User firstName: " + u.getFirstName()); }); System.out.println("filter done!"); }
map()
static void map() { System.out.println("map..."); String firstName = faker.name().firstName(); String lastName = faker.name().lastName(); String email = (firstName + lastName).toLowerCase() + "@gmail.com"; User user = User.builder().firstName(firstName).lastName(lastName).email(email).phoneNumber(faker.phoneNumber().cellPhone()).build(); System.out.println("User: " + user.toString()); user = null; Optional<User> optUser = Optional.ofNullable(user); Optional<String> optEmail = optUser.map(u -> { System.out.println("running map if value is not null"); return u.getEmail(); }); optEmail.ifPresent(em -> { System.out.println("User email: " + em); }); System.out.println("map done!"); }