Java 8  has provided a very strong feature to write code in a better and cleaner way. This can be used to easily replace our null but should it be used everywhere? And with this, we get a question about When to use Java Optional Class.

1. What is Java Optional Class?

Java optional is a generic class, It is a wrapper around another classes object and provides a set of methods.

package java.util;
...
public final class Optional<T> {
    ...
    private final T value;
    ...
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }
    public boolean isPresent() {
        return value != null;
    }
   ...
}

As you can it has variable value and later that value can be retrieved using get.  It has some other important methods which we will discuss later in this blog. Here is a basic example of how we can use Java Optional class.

class Country{  
  private String name = "some name";
  ...
}
//Using null check -Method 1
Country country = new Country();
    
if(country != null){
    System.out.println(country.getName());
}

//Using optional Class -- Method 2
Country country = new Country();		
Optional<Country> optionalOfCountry= Optional.ofNullable(country);
if(optionalOfCountry.isPresent()){
    System.out.println(optionalOfCountry.get().getName());
}

So what the difference between method one and method two, Method 2 doesn’t require ‘null’ keyword but does it look like it has reduced your code and it’s better to read( Different people different opinion)? I feel it’s waste of time to use method 2 here. Then,

2. When to use Java Optional Class?

Let’s start by example.

class Country{  
  State state;
        ...
}

class State{  
  District district;
        ...
}

class District{  
  Village village;
        ...
}

class Village{  
  String villageName = "default name";
        ...
}

Country country = new Country();


//Using null check -Method 1
if(country !=null){
  if(country.getState() !=null){
    if(country.getState().getDistrict() != null){
      if(country.getState().getDistrict() != null){
        if(country.getState().getDistrict().getVillage() != null){
          if(country.getState().getDistrict().getVillage().getVillageName() != null){
            System.out.println(country.getState().getDistrict().getVillage().getVillageName());
          }
          else{
            System.out.println("No village name defined");
          }
        }
      }
    }
  }
}

//Using optional Class and map function -Method 2
Optional<Country> optionalOfCountry= Optional.ofNullable(country);
System.out.println(optionalOfCountry.map(Country::getState)
    .map(State::getDistrict)
    .map(District::getVillage)
    .map(Village::getVillageName)
    .orElse("No village name defined"));

Here we created nested classes and method 1 shows how to null check and get the end value while method 2 use Optional class and its map method to transform the input to an output variable, In the end, we used orElse method to return if everything is null.
Here definitely we can say Optional way handling nulls is more readable and less code. If we conclude we can single whenever there is nested null checks better to wrap the object in Java Optional class and use it rather then writing ugly null check code and in case of one time null check use our oldy goldy null check. Let discuss more on Optional class.

3. Java Optional Class Instantiation

3.1 Initiate an empty Optional

This is used when you want to start with an empty/null value Optional wrapper.

Optional<T> optional = Optional.empty();

3.2 Initiate Optional with an object.

This is used when you want to initialize wrapper with an object, but object can’t be null.

Optional<T> optional = Optional.of(T t);

3.3 Initiate Optional with a nullable object.

This is used when you want to initialize wrapper with an object and object can be null.

Optional<T> optional = Optional.ofNullable(T t);

##3. Java Optional Class Methods

3.3 Get the value of Optional.

This is used when you want to initialize wrapper with an object and object can be null.

T t = optional.get() ;

3.3 Check if the value is present in Optional.

This is used when you want to initialize wrapper with an object and object can be null.

boolean isPresent = optional.isPresent();

3.3 Call consumer if the value is present.

This is used for terminal operations,  what to do if the value is there probably print it. A consumer is a functional interface having only one method which accepts a value and returns nothing.

ifPresent(Consumer<? super T> consumer);

Optional<String> nameOptional = Optional.of("sanjay");
nameOptional.ifPresent(System.out::println);

3.3 Conditional check.

Filters are used to run some predicates on Optional value which return either true or false. Based on predicate result it returns either the same Optional value or empty Optional.

Optional<T> t = optional.filter(Predicate<? super T> predicate);

Optional<Integer> optionalInt = Optional.of(24);
optionalInt = optionalInt.filter(i -> i>0); // the condition returns true so the end value remains same.

optionalInt = optionalInt.filter(i- > i<0); // it return false the end result will be equal to optional.empty();

3.3 Map Optional value to another Optional

Map function takes a functional interface which takes T parameter and return R another parameter.

Optional<U> u = optional. map(Function<? super T, ? extends U> mapper); 

Optional<String> optString = Optional.of("sanjay");
Optional<Int> optInt = optString.map(String::length);
optInt.get(); // return 5

3.3 If null then return another value

This function takes a parameter and returns the passed parameter when the optional value is null.

T t = optional. orElse(T other);

3.3 If null then return the value generated by the supplier.

This is used when you want to initialize wrapper with an object and object can be null.

T t = optional. orElseGet(Supplier<? extends T> other); 

Optional<String> optString = Optional.empty();
double a = optString.orElseGet(Maths:random); //return random value

4. Conclusion

In this blog, we have discussed when to use Java Optional class and what are the important method in this class. This is it about the blog When to use Java Optional Class.