How to Use the Java Optional Properly

How to Use the Java Optional Properly

0 Comments

Last Updated on October 20, 2024 by jt

One of the exceptions that every Java Programmer must have faced is NullPointerException. They are hard to debug and cause unexpected termination of your application. To better handle NullPointerException, Java 8 has introduced the Optional class.
In this post, I’ll explain how to use Optional in Java applications.

Optional Overview

The main benefit of the Optional class is that it prevents unwanted NullPointerExceptions.

Consider this code.

NPEExample.java

package guru.springframework.optionaldemos;

public class NPEExample {

    static String convert(String[] strArr, int index){
        if(strArr[index]!=null)
           return strArr[index].toUpperCase();
        else
            return "Please provide valid input";
    }
    public static void main(String[] args) {
        String[] strArr= new String[5];
        String convertedValue= convert(strArr,3);
        System.out.println(convertedValue);
    }
}

When you run the preceding code, you get NullPointerException, like this.

To prevent this, we can do explicit null checks, like this.
NPEExample.java

package guru.springframework.optionaldemos;

public class NPEExample {

    static String convert(String[] strArr, int index){
        if(strArr[index]!=null)
           return strArr[index].toUpperCase();
        else
            return "Please provide valid input";
    }
    public static void main(String[] args) {
        String[] strArr= new String[5];
        String convertedValue= convert(strArr,3);
        System.out.println(convertedValue);
    }
}

With Optional, the code will now look like this.

String res;
String[] strArr= new String[6];
Optional<String> checkNull = Optional.ofNullable(strArr[5]);
if (checkNull.isPresent()) {
    res = convert(strArr, 5);
    System.out.println(res);
}
else
System.out.println("Value is not present");

In the preceding code, the ofNullable() method returns an Optional describing the given value, if non-null. Otherwise, this method returns an empty Optional. In the preceding code the method returns an empty Optional.

The isPresent() method returns true if a value is present. Otherwise, it returns false. In the preceding code, the isPresent() method will return false, and the program will output Value is not present.

Creating Optional Objects

The Optional class comes with a number of static methods to create Optional objects. The methods are:

  • empty()
  • of()
  • ofNullable()

The empty() Method

private static void emptyOptioal() {
    /*Empty Optional*/
    Optional<String> empty = Optional.empty();
    if(empty.isEmpty()){
        System.out.println("I am an empty optional");
}

The preceding code returns an empty Optional. No value is present for this Optional.

Note: Though, it may be tempting to do check for presence, avoid testing if an object is empty by comparing with {==} against instances returned by Option.empty(). There is no guarantee that it is a singleton. Instead, use isPresent().

The of() Method

The next method is of(). This method returns an Optional with the specified present non-null value.

private static void optionalOf() {
    String name = "Optional";
    Optional<String> opt = Optional.of(name);
    System.out.println(opt);
}

The preceding of() method expects a non-null argument. Otherwise, it will throw a NullPointerException. So take precaustion of caaling this method, if you are not sure whether the parameter is null or not null.

The best practice is to use the ofNullable() method.

The ofNullable() Method of the Optional Class

The ofNullable () method returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional.

You can refactor your code like this:

// Possible null value
Optional<String> optional = Optional.ofNullable(getName());

private static String getName(){
    String name = "Im an Optional";
    return (name.length() > 5) ? name :  null;
}

In the preceding code, if we pass in a null reference, it doesn’t throw an exception but rather returns an empty Optional object:

Below is the code, you can refer to.

OptionalCreation.java

package guru.springframework.optionaldemos;

import java.util.Optional;

public class OptionalCreation {

    public static void main(String[] args) {
        emptyOptioal();
        optionalOf();
        // Possible null value
        Optional<String> optional = Optional.ofNullable(getName());
        System.out.println(optional);


    }
    private static String getName(){
        String name = "Im an Optional";
        return (name.length() > 5) ? name :  null;
    }

    private static void optionalOf() {
        String name = "Optional";
        Optional<String> opt = Optional.of(name);
        System.out.println(opt);
    }

    private static void emptyOptioal() {
        /*Empty Optional*/
        Optional<String> empty = Optional.empty();
        if(empty.isEmpty()){
            System.out.println("I am an empty optional");
        }
    }
}

Checking for Values in an Optional

The Optional class has two methods called isEmpty() and isPresent(). Both the methods return a boolean value which indicates whether or not a value is present in the Optional.

The isEmpty() method checks If a value is not present, and accordingly will returns true, otherwise false.

On the other hand, the isPrsent() method returns true If a value is present,, otherwise false.

The code to use the methods is this.

Optional op1 = Optional.empty();
System.out.println(op1.isEmpty());
System.out.println(op1.isPresent());
Optional op2 = Optional.of("Optional");
System.out.println(op2.isEmpty());
System.out.println(op2.isPresent());

The output of the preceding code is this.

true
false
false
true

OrElse() and OrElseGet() of the Optional Class

Optional comes with the orElse() method that will always call the given function whether you want it or not. It is also regardless of Optional.isPresent() value.

The following code shows an example of orElse() method.

Optional<Integer> op  = Optional.empty();
// print value
System.out.println("Optional: " + op);

if(op.isEmpty())
        // orElse value
        System.out.println("Value by orElse " + op.orElse(100));

Note: On the other hand, orElseGet() will only call the given function when the Optional.isPresent() == false.

Retrieving Values from Optional

The Optional class provides a get() method that returns the value if present in the Optional. Otherwise, this method throws NoSuchElementException.

The following code shows using the get() method.

package guru.springframework.optionaldemos;

import java.util.Optional;

public class OptionalGet {
    public static void main(String[] args) {
        Optional op1 = Optional.of("Hello World");
        System.out.println(op1.orElse("Default Value"));
        Optional opt2=Optional.empty();
        System.out.println(opt2.orElse("Default Value"));

    }
}

The output of the preceding code is this.

Hello World
Exception in thread "main" java.util.NoSuchElementException: No value present
  at java.base/java.util.Optional.get(Optional.java:143)
  at guru.springframework.optionaldemos.OptionalGet.main(OptionalGet.java:10)

To avoid the exception, you can use the orElse() method to return a default value, like this.

Optional op1 = Optional.of("Hello World");
System.out.println(op1.orElse("Default Value"));
Optional opt2=Optional.empty();
System.out.println(opt2.orElse("Default Value"));

The output of the preceding code is this.

Hello World
Default Value

The Optional class provides a orElseThrow() method that you can use to throw a custom exception when a value is not present in the Optional.

An example to use the orElseThrow() method is this.

OptionOrElseThrow.java

package guru.springframework.optionaldemos;

import java.util.Optional;

public class OptionOrElseThrow {

    public static void main(String[] args) throws Throwable {
        String email= null;
        Optional emailOpt=Optional.ofNullable(email);
        System.out.println(emailOpt.orElseThrow(()->new IllegalArgumentException("Email cannot be null")));
    }
}
The output on running the preceding code is this.
Exception in thread "main" java.lang.IllegalArgumentException: Email cannot be null

Performing Operations on Optional

The filter() Method

The Optional class contains a filter() method that filters a value, if present, against a given predicate. This method returns an Optional describing the value.

If there is no value present in the Optional, then this method returns an empty Optional object.

An example of using the filter() method is this.

 private static void filterDemo() {
        Optional opt1=Optional.of("Hello! Optional Example");
        Predicate<String> predicate1 = s -> s.contains("Example");
        Optional<String> result1 = opt1.filter(predicate1);
        System.out.println(result1.isPresent());

        Predicate<String> predicate2 = s -> s.startsWith("Hello");
        Optional<String> result2 = opt1.filter(predicate2);
        System.out.println(result2.isPresent());
}

The output of the preceding code is this.

true
true

The map() Method

The map() method of Optional returns an Optional describing the result of applying the given mapping function to the value in the Optional. If no value is present this method returns an empty Optional.

The following code shows the use of the map() method.

private static void mapDemo() {
        Optional<String> opt1=Optional.of("Hello! Optional Example");
        System.out.println(opt1.map(String::toUpperCase).get());
}

The output on calling the preceding method is this.

HELLO! OPTIONAL EXAMPLE

Summary

The Optional class is an attempt to reduce the number of null pointer exceptions in Java systems. However, I have seen developers using Optional incorrectly.

One common mistake is assigning null to an optional variable, like this.

public Optional<Product> getProduct(int id) {
    // perform a search for product 
   Optional<Product> product = null; // in case no product
   return product; 

}

The correct approach is to replace the line, which initializes the Optional with an empty Optional like this.

Optional<Product> product = Optional.empty();

Another typical mistake developers make is directly calling the get() method. If the Optional is empty, the call to get will throw NoSuchElementException. Instead always do a check with the isPresent() method before calling get().

The source code of this post is present on Github.

About SFG Contributor

Staff writer account for Spring Framework Guru

    You May Also Like

    Leave a Reply

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

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