Java Optional was introduced in Java 1.8. Imagine Optional as a container that can hold objects and it could be empty sometimes.
Initialize an Optional.
We can initialize an empty Optional with Optional.empty()
. Avoid using null to initialize an Optional. It is not a good practice.
Optional<Customer> customer = null; //Not a good practice.
Optional<Customer> customer = Optional.empty(); //An empty Optional.
Optional<Customer> customer = Optional.of(new Customer("John")); //with value
Get value from an Optional
- Using
orElse
method.
To get value from an Optional most of the time we can use orElse
method. When the Optional is empty using get()
method will trigger java.util.NoSuchElementException
public static void main(String[] args) {
Optional<Customer> customer = Optional.empty();
System.out.println(customer.get()); //NoSuchElementException
}
Result:
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:143)
Instead use orElse
method as shown below.
public static void main(String[] args) {
Optional<Customer> customer = Optional.empty();
System.out.println(customer.orElse(null)); //print null
Optional customer1 = Optional.of(new Customer("john"));
System.out.println(customer1.orElse(null)); //print Customer John.
}
- Using
orElseGet
method.
Don’t use orElse
method for getting a value that involves heavy computing. Because the code in orElse
method gets executed even if the Optional is not empty. Consider the below code. Here even though the object is available in cache, orElse
executes the getFromDB method as we can see from the output. It is not good for performance.
public static void main(String[] args) {
Customer customer =
getFromCache().
orElse(getFromDB().
orElseThrow(() ->
new RuntimeException("Customer Not found")));
System.out.println(customer);
}
public static Optional<Customer> getFromCache(){
System.out.println("getFromCache");
return Optional.of(new Customer("From Cache"));
}
public static Optional<Customer> getFromDB(){
System.out.println("getFromDB");
return Optional.of(new Customer("From DB"));
}
//OUTPUT//
getFromCache
getFromDB
Customer{name='From Cache'}
If we change the above code to use orElseGet
as shown below, getFromDB method will not be executed if the object is available in Cache.
Customer customer =
getFromCache().
orElseGet(()->getFromDB().
orElseThrow(() ->
new RuntimeException("Customer Not found")));
System.out.println(customer);
//OUTPUT//
getFromCache
Customer{name='From Cache'}
Note: orElseGet
method accepts a Supplier.
- Do computation on value if present in Optional.
To do some computation on values of an Optional if present, use ifPresent(Consumer<? super T> action)
method.
Optional<Customer> customer = Optional.of(new Customer("John"));
customer.ifPresent((c)->System.out.println(c.getName().length()));
Throw Exception if Optional is empty.
Use orElseThrow
method to throw Exception if the Optional is empty.
Customer customer = getFromDB().
orElseThrow(()->new RuntimeException("Customer Not Found"));
System.out.println(customer);