Java – Optional

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:

  • It helps to avoid NullPointerExceptions.
  • It makes code more readable and maintainable.
  • It can be used to represent a variety of different scenarios, such as when a value is not yet known, when a value may be null, or when a value is optional.

isPresent()

The Optional class provides the isPresent() method, which is used to check whether an Optional object contains a nonnull 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!");
}

 

Github Code Reference




Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published. Required fields are marked *