Java Optional Class

In Java 8, Java added a new class Optional in java.util package. This class is used to manage and control the NullPointerException in Java. The NullPointerException is the most occurred exception in day to day programming due to uninitialized object or null pointer.

Due to This exception, our program terminates abnormally and the program leads to unexpected output.

To handle this situation Java provides Optional class that is a container object which may or may not contain a non-null value. It provides lots of methods to check null or not null values and makes our program NullPointerException free.

You can understand the situation by this example which is written before the Java 8 and due to uninitialized variable leads to program termination by throwing the NullPointerException.

Example: Without Optional Class

It is common when we create a variable but forget to initialize it but when we use it. It does not work and terminates the program.

public class Main {
	String name;	// uninitialized variable
	public static void main(String[] args){
		Main m = new Main();
		/*
		 * 
		 * tons of line of code
		 * 
		 */
		// fetching name in somewhere in the code.
		char ch = m.name.charAt(0);
		System.out.println(ch);  // NullPointerException
	}
}


Exception in thread "main" java.lang.NullPointerException

Example: With Optional Class

In this example, we are using Optional class to check whether the variable is null or not. To check, we used isPresent() method that returns true if the variable is not null.

import java.util.Optional;

public class Main {
	String name;	// uninitialized variable
	public static void main(String[] args){
		Main m = new Main();
		/*
		 * 
		 * tons of line of code
		 * 
		 */
		// fetching name in somewhere in the code.
		// Handling null using Optional class
        Optional<String> isNull = Optional.ofNullable(m.name);  
        if(isNull.isPresent()) {
        	char ch = m.name.charAt(0);
    		System.out.println(ch);  // No NullPointerException
        }else {
        	System.out.println("Value is null");
        }
	}
}


Value is null

Optional Declaration

public final class Optional<T> extends Object

Optional Methods

The following table contains methods of Optional class such as empty(), of(), offNullable() etc.

Methods Description
public static <T> Optional<T> empty() It returns an empty Optional object. No value is present for this Optional.
public static <T> Optional<T> of(T value) It returns an Optional with the specified present non-null value.
public static <T> Optional<T> ofNullable(T value) It returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional.
public T get() If a value is present in this Optional, return the value, otherwise throws NoSuchElementException.
public boolean isPresent() It returns true if there is a value present, otherwise false.
public void ifPresent(Consumer<? super T> consumer) If a value is present, invoke the specified consumer with the value, otherwise do nothing.
public Optional<T> filter(Predicate<? super T> predicate) If a value is present, and the value matches the given predicate, return an Optional describing the value, otherwise return an empty Optional.
public <U> Optional<U> map(Function<? super T,? extends U> mapper) If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise, return an empty Optional.
public <U> Optional<U> flatMap(Function<? super T,Optional<U> mapper) If a value is present, apply the provided Optional-bearing mapping function to it, return that result, otherwise return an empty Optional.
public T orElse(T other) It returns the value if present otherwise returns others.
public T orElseGet(Supplier<? extends T> other) It returns the value if present, otherwise invoke other and return the result of that invocation.
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X extends Throwable It returns the contained value, if present, otherwise throw an exception to be created by the provided supplier.
public boolean equals(Object obj) Indicates whether some other object is "equal to" this Optional or not. The other object is considered equal if:
  • It is also an Optional and;
  • Both instances have no value present or;
  • the present values are "equal to" each other via equals().
public int hashCode() It returns the hash code value of the present value, if any, or returns 0 (zero) if no value is present.
public String toString() It returns a non-empty string representation of this Optional suitable for debugging. The exact presentation format is unspecified and may vary between implementations and versions.

Example: isPresent() and ifPresent()

Let's create another example to understand the isPresent() and ifPresent() method. Both methods belong to Optional class, the isPresent() method returns true if the variable is not null and the ifPresent() method executes only if the variable is not null, else it does nothing.

import java.util.Optional;
public class Main {
	String name;	// uninitialized variable
	public static void main(String[] args){
		Main m = new Main();
		m.name = "Rohan"; // Initializing variable
        Optional<String> name = Optional.ofNullable(m.name);  
        if(name.isPresent()) {
        	char ch = m.name.charAt(0);
    		System.out.println(ch);  // No NullPointerException
        }else {
        	System.out.println("Value is null");
        }
        // ifPresent()
        name.ifPresent(n -> {
        						System.out.println("Value is present");
        						System.out.println("Value start with "+ m.name.charAt(0));
        					}
        				);
        

	}
}


R
Value is present
Value start with R

Example: orElse() Method

The orElse() method is used to return a specified value if the variable is null. This method is used to set an alternate value for a variable so that if a variable is empty then we can get a specified value rather than null.

import java.util.Optional;
public class Main {
	public static void main(String[] args){
		Optional<String> name = Optional.of("Rohan");
		Optional<String> lName = Optional.empty();

		// orElse
		String other = name.orElse("Sohan");
		System.out.println(other);
		// empty
		other = lName.orElse("Sohan");
		System.out.println(other);
	}
}


Rohan
Sohan

Example: orElseGet()

The orElseGet() method is similar to orElse() method except it allows calling an implementation such as a lambda expression or a function. See the example below.

import java.util.Optional;
public class Main {
	static String otherVal() {
		return "Value not Present";
	}

	public static void main(String[] args){
		Optional<String> name  = Optional.of("Rohan");
		Optional<String> lName = Optional.empty();

		// orElseGet
		String other = name.orElseGet(() -> otherVal());
		System.out.println(other);
		// empty
		other = lName.orElseGet(() -> otherVal());
		System.out.println(other);
	}
}


Rohan
Value not Present

Example: filter() Method

The filter() method returns an optional and takes a predicate as an argument. So we can pass a lambda expression to filter the result as we did in the below example.

import java.util.Optional;
public class Main {
	public static void main(String[] args){
		Optional<String> name  = Optional.of("Rohan");
		Optional<String> lName = Optional.empty();

		// filter
		Optional <String> other  = name.filter(n->n.equals("Rohan"));
		System.out.println(other);
		other  = name.filter(n->n.equals("rohan"));
		System.out.println(other);
	}
}


Optional[Rohan]
Optional.empty