The java.util.Optional<T>
container object is a wrapper around an object, which may or may not
contain a non-null value.
So why do we need Optional ???
Java developers often times encounter the dreaded NullPointerException.
This happens when one accesses a reference object whose value ends up
being null.
In Java, a null value is used to indicate
absence of a value. In contrast, in functional programming languages
(like Haskell or Scala), a function call always returns a special value,
which allows one to get the actual return value (if there is one) or can
indicate the absence of a value. This is much more elegant and safer.
Let us jump into an example to understand why we need Optional.
In this hypothetical example, we will search a catalog for a product
and display the product name and its price.
The following is a simple class for product:
The following is a simple catalog application that is finding two
products - A and C and displaying their information:
Executing the program from Listing.2 will generate the following
output:
Output.1
Name: A, Price: 1.25
java.lang.NullPointerException
at com.polarsparc.java8.Catalog.findProduct(Catalog.java:48)
at com.polarsparc.java8.Catalog.main(Catalog.java:26)
In Listing.2, we did not check for nulls and
hence this exception.
The following is the safer version of Listing.2 using defensive coding
practices:
Executing the program from Listing.3 will generate the following
output:
Output.2
Name: A, Price: 1.25
As can be observed from Listing.3, even for this very basic
application, one needs to check every reference for nulls.
The following simple test program illustrates the basic usage of Optional:
Executing the program from Listing.4 will generate the following
output:
Output.3
java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:135)
at com.polarsparc.java8.OptionalTest.main(OptionalTest.java:20)
java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.<init>(Optional.java:96)
at java.util.Optional.of(Optional.java:108)
at com.polarsparc.java8.OptionalTest.main(OptionalTest.java:29)
Optional
Java 8 Optional
The code in Listing.4 needs a little explanation.
get() :: Returns the value wrapped
by Optional if it is not null.
Else throws NoSuchElementException
exception
Optional.empty() :: Returns an
un-initialized Optional instance
Optional.of() :: Returns an
initialized Optional instance
wrapping the specified value. If the specified value is null,
throws NullPointerException exception
Optional.ofNullable() :: Returns an
initialized Optional instance
wrapping the specified value even if the specified value is null
isPresent() :: Returns true
if the Optional instance contains a
non-null value. Else returns false
ifPresent(Consumer) :: Invoke the
specified Consumer if the Optional
instance contains a non-null value
!!! ATTENTION !!!
Trying to access the value of an un-initialized empty Optional with
get() will result in the following exception:
java.util.NoSuchElementException: No value present
!!! ATTENTION !!!
Trying to create an Optional instance with of() on a null value will
result in the following exception:
java.lang.NullPointerException
Now that we have briefly explored Optional,
the following is the refactored simple class for product:
The following is the more elegant version of Listing.3 using Optional: