Java Optional Class Guide with Examples

In this article, we will learn Java Optional Class with examples. The optional class is introduced in Java 8 and helps us to deal with null pointer exceptions. Sometimes it is a nightmare to deal with NullPointerException when we are writing Java codes. To eliminate this annoying problem,  we can use Java 8 Optional Class and its features. By the way, the Optional Class has been improved in other Java JDK versions by adding extra features which we will learn in this article. We will handle potentially nullable fields with Optional Class’s methods.

Let’s learn the Optional class features one by one together! :)

Java Optional Class Examples

In each example, we will see examples for null, empty, and “not empty and not null” Optional value. First, let’s create these Optional objects in our test class.

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class OptionalExamples {
    @BeforeEach
    public void setup(TestInfo testInfo) {
        System.out.println("Test name: " + testInfo.getDisplayName());

    }

    @AfterEach
    public void tearDown() {
        System.out.println();
    }

    private Optional<String> returnNullMessage() {
        return Optional.ofNullable(null);
    }

    private Optional<String> returnEmptyMessage() {
        return Optional.empty();
    }

    private Optional<String> returnCustomMessage() {
        return Optional.of("SW Test Academy!");
    }

    //We will continue from here...

Yes, we declared null, empty, and valid String Optional objects. Also, we will use the below Supplier and Runnable functions in the tests. We will see the details in the examples one by one.

Supplier<String> customMessageSupplier = () -> "SW Test Academy!";

Supplier<Optional<String>> optionalTextSupplier = () -> Optional.of("This is an optional text!");

Supplier<String> anotherTextSupplier = () -> {
    System.out.println("Returning an another text.");
    return "Another Text!";
};

private final Runnable runnable = () -> System.out.println("Value is null or empty!");

//We will continue from here...

We have defined our variables and some functional interface functions such as Supplier and Runnable for our tests. Now, let’s start to write our tests and understand the Java Optional Class features.

isPresent() Example

We can use isPresent() method to check the value’s existence in the Optional object. If the value should be non-null and not empty, the isPresent() method will return true otherwise we will get false. Let’s see this behavior in the below example.

Returns: true if a value is present, otherwise false.

private Optional<String> returnNullMessage() {
    return Optional.ofNullable(null);
}

private Optional<String> returnEmptyMessage() {
    return Optional.empty();
}

private Optional<String> returnCustomMessage() {
    return Optional.of("SW Test Academy!");
}

@Test
@Order(1)
public void isPresentTest() {
    String result1 = returnNullMessage().isPresent() ? returnNullMessage().get() : "Value is null or empty!";
    String result2 = returnEmptyMessage().isPresent() ? returnEmptyMessage().get() : "Value is null or empty!";
    String result3 = returnCustomMessage().isPresent() ? returnCustomMessage().get() : "Value is null or empty!";
    System.out.println(result1);
    System.out.println(result2);
    System.out.println(result3);
}

Output

As you seen below, if the value is null and empty, we got false from isPresent() method, and the code prints the “Value is null or empty!” for the first two cases which are null and empty values. For the third case, the returnCusomMessage() method returns a “not empty  and  non-null” optional string value and according to this, the isPresent() method returns true, and finally the code prints the content of the value of returnCustomMessage() method which is “SW Test Academy!”.

optional ispreset() method example in java

isEmpty() Example

isEmpty() is behaving opposite of isPresent() method. If the optional object’s value is empty or null, it returns true if not it returns false. It comes with Java 11.

Returns: true if a value is not present, otherwise false.

private Optional<String> returnNullMessage() {
    return Optional.ofNullable(null);
}

private Optional<String> returnEmptyMessage() {
    return Optional.empty();
}

private Optional<String> returnCustomMessage() {
    return Optional.of("SW Test Academy!");
}

@Test
@Order(2)
public void isEmptyTest() {
    String result1 = returnNullMessage().isEmpty() ? "Value is null or empty!" : returnNullMessage().get();
    String result2 = returnEmptyMessage().isEmpty() ? "Value is null or empty!" : returnEmptyMessage().get();
    String result3 = returnCustomMessage().isEmpty() ? "Value is null or empty!" : returnCustomMessage().get();
    System.out.println(result1);
    System.out.println(result2);
    System.out.println(result3);
}

Output

As seen in the screenshot below, for the first and second cases the optional objects’ values are null and empty. That’s why the isEmpty() method returns true and the code prints the “Value is null or empty!”, in the third case, the returnCustomMessage() returns an optional string, and the isEmpty() method returns true and according to these the code prints the value of returnCustomMessage() which is “SW Test Academy!”.

optional isempty() method in java

or() Example

The or() method comes with Java 9 and if a value is present, returns an Optional describing the value, otherwise returns an Optional produced by the supplying function.

Params: supplier – the supplying function that produces an Optional to be returned.
Returns: returns an Optional describing the value of this Optional, if a value is present, otherwise, an Optional produced by the supplying function.
Throws: NullPointerException – if the supplying function is null or produces a null result.

In the below example, we will see the or() functions behavior.

private Optional<String> returnNullMessage() {
    return Optional.ofNullable(null);
}

private Optional<String> returnEmptyMessage() {
    return Optional.empty();
}

private Optional<String> returnCustomMessage() {
    return Optional.of("SW Test Academy!");
}

Supplier<Optional<String>> optionalTextSupplier = () -> Optional.of("This is an optional text!");

@Test
@Order(3)
public void orTest() {
    Optional<String> result1 = returnNullMessage().or(optionalTextSupplier);
    Optional<String> result2 = returnEmptyMessage().or(optionalTextSupplier);
    Optional<String> result3 = returnCustomMessage().or(optionalTextSupplier);
    System.out.println(result1);
    System.out.println(result2);
    System.out.println(result3);
}

Output

As seen in the screenshot below, in the first and second cases the values are null and empty, values are not present and the or function returns the optionalTextSupplier function. In the third case, the value is present for returnCustomMessage() method and the or() method returns the returnCustomMessage() function’s optional string value.

optional or method in java

orElse() Example

If a value is present, the orElse() method returns the value, otherwise, it returns the other. 

Params: other – the value to be returned, if no value is present. May be null.
Returns: the value, if present, otherwise other.

private Optional<String> returnNullMessage() {
    return Optional.ofNullable(null);
}

private Optional<String> returnEmptyMessage() {
    return Optional.empty();
}

private Optional<String> returnCustomMessage() {
    return Optional.of("SW Test Academy!");
}

@Test
@Order(4)
public void orElseTest() {
    String result1 = returnNullMessage().orElse(customMessageSupplier.get());
    String result2 = returnEmptyMessage().orElse(customMessageSupplier.get());
    System.out.println(result1);
    System.out.println(result2);
}

Output

As you can see below, the value is not present in both cases because they are null and empty, that’s why orElse() returns the customMessageSupplier.get() which is “SW Test Academy!”.

orElse() optional method in java

orElseGet() Example

If a value is present, orElseGet() method returns the value, otherwise, it returns the result produced by the supplying function. 

Params: supplier – the supplying function that produces a value to be returned.
Returns: the value, if present, otherwise the result produced by the supplying function.
Throws: NullPointerException – if no value is present and the supplying function is null.

private Optional<String> returnNullMessage() {
    return Optional.ofNullable(null);
}

private Optional<String> returnEmptyMessage() {
    return Optional.empty();
}

private Optional<String> returnCustomMessage() {
    return Optional.of("SW Test Academy!");
}

@Test
@Order(5)
public void orElseGetTest() {
    String result1 = returnNullMessage().orElseGet(customMessageSupplier);
    String result2 = returnEmptyMessage().orElseGet(customMessageSupplier);
    System.out.println(result1);
    System.out.println(result2);
}

Output

As you can see below, the value is not present in both cases because they are null and empty, that’s why orElseGet() returns the customMessageSupplier which is “SW Test Academy!”.

orElseGet() method in java

orElse() vs orElseGet() Example

In the below example, the returnCustomMessage() returns not null or empty value, and we will get the custom message but also the object inside orElse() has been created. That’s why we will see the print statement inside anotherTextSupplier() function in the below example. This is of the main difference between orElse() and orElseGet().

Supplier<String> customMessageSupplier = () -> "SW Test Academy!";

Supplier<String> anotherTextSupplier = () -> {
    System.out.println("Returning an another text.");
    return "Another Text!";
};

@Test
@Order(6)
public void orElse_vs_OrElseGet_Test() {
    System.out.println("orElse() Test Starting!");
    String orElseResult = returnCustomMessage().orElse(anotherTextSupplier.get());
    System.out.println("Result of orElse(): " + orElseResult + "\norElse() Test Finished!\n");

    System.out.println("orElseGet() Test Starting!");
    String orElseGetResult = returnCustomMessage().orElseGet(anotherTextSupplier);
    System.out.println("Result of orElseGet(): " + orElseGetResult + "\norElseGet() Test Finished!");
}

Output

As you see the screenshot below, the orElse() method also printed the “Returning an another text.” inside anotherTextSupplier() function but the orElseGet() implementation anotherTextSupplier() function did not initiated.

orElse vs orElseGet in java optional class

orElseThrow() Example

If a value is present, the orElseThrow() method returns the value, otherwise, it throws an exception produced by the exception supplying function.

Params:

  • exceptionSupplier – the supplying function that produces an exception to be thrown
  • Type parameters: <X> – Type of the exception to be thrown

Returns: The value, if present.

Throws:

  • X – if no value is present
  • NullPointerException – if no value is present and the exception supplying function is null.
private Optional<String> returnNullMessage() {
    return Optional.ofNullable(null);
}

private Optional<String> returnEmptyMessage() {
    return Optional.empty();
}

private Optional<String> returnCustomMessage() {
    return Optional.of("SW Test Academy!");
}

@Test
@Order(7)
public void orElseThrow() {
    Assertions.assertThrows(IllegalArgumentException.class, () -> returnNullMessage().orElseThrow(IllegalArgumentException::new));
    Assertions.assertThrows(IllegalArgumentException.class, () -> returnEmptyMessage().orElseThrow(IllegalArgumentException::new));
    Assertions.assertEquals("SW Test Academy!", returnCustomMessage().orElseThrow(IllegalArgumentException::new));
}

Output

As seen in the screenshot below, in the first two cases, we expect the IllegalArgumentException because the functions are returning “null” and “empty” values, and orElseThrow() method throws the defined IllegalArgumentException. In the third case, returnCustomMessage() method returns a “non-null and not empty” value (present value) and the orElseThrow() method returns that value which is “SW Test Academy!”. That’s why all assertions have been passed in this test.

orElseThrow() method in java

ifPresent() Example

If a value is present, the ifPresent() method performs the given action with the value, otherwise does nothing.

Params: action – the action to be performed, if a value is present.
Throws: NullPointerException – if the value is present and the given action is null.

private Optional<String> returnNullMessage() {
    return Optional.ofNullable(null);
}

private Optional<String> returnEmptyMessage() {
    return Optional.empty();
}

private Optional<String> returnCustomMessage() {
    return Optional.of("SW Test Academy!");
}

@Test
@Order(8)
public void ifPresent() {
    returnNullMessage().ifPresent(message -> System.out.println("The Message is: " + message));
    returnEmptyMessage().ifPresent(message -> System.out.println("The Message is: " + message));
    returnCustomMessage().ifPresent(message -> System.out.println("The Message is: " + message));
}

Output

As you see below, only in the third case the value is present and the code prints the value of the returnCustomMessage() function.

ifPresent() method in java

ifPresentOrElse() Example

The ifPresentOrElse() function comes with Java 9. If a value is present, the ifPresentOrElse() method performs the given action with the value, otherwise, it performs the given empty-based action.

Params:

  • action – The action to be performed, if a value is present.
  • emptyAction – The empty-based action to be performed, if no value is present.

Throws: NullPointerException – if a value is present and the given action is null, or no value is present and the given empty-based action is null.

Here we can see how parameters look like when IntelliJ helps us when we are clicking “command + P” in Mac and “ctrl + P” in Windows. To learn Runnable Interface, you can visit this article.

intelliJ functions parameter help

private Optional<String> returnNullMessage() {
    return Optional.ofNullable(null);
}

private Optional<String> returnEmptyMessage() {
    return Optional.empty();
}

private Optional<String> returnCustomMessage() {
    return Optional.of("SW Test Academy!");
}

private final Runnable runnable = () -> System.out.println("Value is null or empty!");

@Test
@Order(9)
public void ifPresentOrElseTest() {
    returnNullMessage().ifPresentOrElse(message -> System.out.println("The Message is: " + message), runnable);
    returnEmptyMessage().ifPresentOrElse(message -> System.out.println("The Message is: " + message), runnable);
    returnCustomMessage().ifPresentOrElse(message -> System.out.println("The Message is: " + message), runnable);
}

Output

As seen on the screenshot below, in the first two cases because of null and empty return values, the runnable function is called. In the third case, the returning value is a present and a valid string which is “SW Test Academy!” and the code prints the first parameter of ifPresentOrElse() method which is “message -> System.out.println(“The Message is: ” + message)“.

ifPresentOrElse() optional method in java

Optional Map() Function Example

If a value is present, the map() function returns an Optional describing the result of applying the given mapping function to the value, otherwise returns an empty Optional. If the mapping function returns a null result then this method returns an empty Optional.

@Test
@Order(10)
public void optionalMapExample() {
    Optional<Integer> optional1 = Optional.empty();
    System.out.println("First Example Starting!");
    optional1
        .map(num -> Math.pow(num, 3))
        .ifPresent(System.out::println);

    System.out.println("Second Example Starting!");
    Optional<Integer> optional2 = Optional.of(2);
    optional2
        .map(num -> Math.pow(num, 3))
        .ifPresent(System.out::println);
}

Output

As seen on the screenshot below, when the value is empty we don’t get any result because the value is not present, and in the second case the value is present which is 2 and the result is printed by the code as the power of 2 over 3 as 8.

map() function with Optionals

Optional filter() Function Example

If a value is present, and the value matches the given predicate, the filter() method returns an Optional describing the value, otherwise returns an empty Optional.

@Test
@Order(11)
public void optionalFilterExample() {
    System.out.println("First Example Starting!");
    Optional<String> optional1 = Optional.empty();
    optional1
        .filter(text -> text.length() > 3)
        .ifPresent(System.out::println);

    System.out.println("Second Example Starting!");
    Optional<String> optional2 = Optional.of("SW Test Academy!");
    optional2
        .filter(text -> text.contains("SW Test Academy"))
        .ifPresent(System.out::println);
}

Output

As seen on the screenshot below, when the value is empty we don’t get any result because the value is not present, and in the second case the value is “not empty and not null” and it contains “SW Test Academy” so it passed through the filter() method, and then the ifPresent() method returns true, and finally the code prints “SW Test Academy!”

filter() method in optionals

GitHub Project

https://github.com/swtestacademy/java-functional/blob/main/src/test/java/functional/stream/optional/OptionalExamples.java

In this article, I tried to cover the most important functions in Java Optional Class. I used the latest LTS version of Java which is currently Java 17 for the examples and I highly suggest using the latest LTS version of Java in your projects. 

Thanks for reading,
Onur Baskirt

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.