Deal with `NullPointerException` with Java8 Optional

SUBHAM MAJAVADIYA
3 min readJan 13, 2021

--

As Developer we all Tired of handling NullPointerException while writing code in any programming language and to avoid that we put null checks before accessing the value of any object.

Furthermore, every object can either contain a value or not. If it does, its value is stored in the memory and the variable which we are using has a reference to that object. If the object contains no value, this defaults to null a special placeholder denoting the absence of a value.

To deal with NullPointerException in a much cleaner way Java8 provides Optional Class.

An Optional is essentially a container object which may or may not contain a non-null value. It is designed either to store a value or to be “empty”. it allows implicit null-checking and a good number of API to deal with null, for every object represented as an Optional. This means the developer is no longer responsible to do explicit null-checking that will be taken care of by the Optional class.

So let's quickly go through the various API available to create and access Optional for any object for example.

We will be using our below classes for all the example, the Product class:

public class Product{
private Seller seller;
private String name;
// Constructor, Getters and Setters
}

Creating Optionals

of()

The first approach to creating Optionals is using the .of() API, passing a reference to a non-null object in case of null the method throw NullPointerException:

Product product = new Product();
Optional<Product> optionalProduct = Optional.of(product);

ofNullable()

If product is allowed to be a null, instead of the .of() API, we would use the .ofNullable() method. They perform the same if the value is non-null. The difference is obvious when the reference points to null in which case - the .ofNullable() is perfectly contempt with this piece of code:

Product product = new Product();
Optional<Product> optionalProdcut = Optional.ofNullable(product);

empty()

And finally, instead of wrapping an existing reference variable (null or non-null), we can create a null value in the context of an Optional. It's kind of like an empty container which returns an empty instance of Optional:

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

Accessing Values with Optional

Ah, its time to access the object value once we have created Optionals for any object reference.

get()

So before accessing the value using get() API, we should always check that the value exists using isPresent() API, otherwise, get() will throw NoSuchElementException.
isPresent() will return true if the value is present otherwise false.

Product product = new Product();
Optional<Product> optionalProduct = Optional.ofNullable(product);
if(optionalProduct.isPresent()){
System.out.println(optionalProduct.get());
}

Another way to verify the presence of a value in the Optional instance is by using ifPresent() as shown below. In this scenario, the output on the terminal will be empty as the Optional is empty.

Optional<Product> emptyProduct = Optional.empty();
emptyProduct.ifPresent(product -> System.out.println(optionalProduct.get()));

orElse() || orElseGet() || orElseThrow ()

if we use get() with empty Optional, the method invocation will throw NoSuchElementException but in some cases instead of the exception, we want to return the default value. By using orElse() API we could achieve that.

Product deFaultproduct = new Product();
Optional<Product> emptyProduct = Optional.empty();
System.out.println(emptyProduct.orElse(deFaultproduct));

Instead of providing the default value directly as an argument, by using orElseGet() we can use a Supplier interface and return the result if the value is not present with Optionals.

Optional<Product> emptyProduct = Optional.empty();
System.out.println(emptyProduct.orElseGet(() -> new Product()));

Instead of returning an alternative/default value (as we’ve seen in the previous above example), sometimes we want to throw an exception, to indicate the unavailability of the value to the accessor, which can be achieved by using orElseThrow().

Optional<Product> emptyProduct = Optional.empty();
emptyProduct.orElseThrow(new CustomException("product not found"));

Conclusion

The Optional class comes in with a lot of APIs which has made the life of all the developers easy, who are using it. So start using the Optional class wherever you can and save yourself from fixing issues of unnecessary NullPointerExceptions.

Reference: https://www.oracle.com/technical-resources/articles/java/java8-optional.html

--

--

SUBHAM MAJAVADIYA

Senior Software Engineer at Gojek | Ex-Engati Chatbot Platform | NITD