Your Guide to Java 8 Optional
Your Guide to Java 8 Optional
It's never too late to dive into Java 8 goodies. Let's take a look!
Join the DZone community and get the full member experience.Join For Free
One of the most common exceptions Java programmers face is the NullPointerExceptions. This exception is thrown by the JVM at runtime as a runtime exception.
As we all know, a NullPointerException occurs when the application requires an object but it found a null value. Null value cases are one of the most common exceptions overlooked by Java programmers.
You may also like: 26 Reasons Why Using Optional Correctly Is Not Optional
Null values need to be handled in the application before proceeding with the usual business logic to avoid this exception at runtime. This leads to unnecessary null checks.
To deal with such type of boilerplate code for null values in Java, a new type Optional<T> was introduced in Java 8.
What Is the Problem Without Java 8 Optional?
According to Oracle, Java 8 Optional works as a container type for the value which is probably absent or null. Java Optional is a final class present in the java.util package.
Let’s check out the problem without Java 8 Optional.
Suppose we have the following method in our application. This method retrieves the employee details from the database and returns it for the respective id :
Suppose the provided id is not present in the database. Then, the method will return the null value. Now, if we have the code written below:
The code above will throw the NullPointerException at runtime as the programmer has not null checked the value before using it.
How Do Java 8 Optionals Provide the Solution?
Now, let us see how Java 8 Optional will solve the above problem and help in eliminating the
Below is the modification required for the above code :
In the above code, we are indicating to the client by returning Optional<Employee> that there is a possibility that an employee may not exist with the given id.
Now, in the client’s application, this fact needs to be explicitly communicated.
The client should be written as follows:
You can see that we have created one Optional object in the above code’s first line. Now, we are allowed to use various utility methods with the Optional object.
ifPresent() in the above code snippet calls the provided lambda expression only if the employee is present; otherwise, it does not.
Advantages of Java 8 Optional
Below are some of the listed advantages of using Java 8 Optional:
- NullPointerException is prevented at runtime.
- Null value checking is not required in the application.
- Boilerplate code is not required.
- It's easy to develop clean and neat APIs.
Java 8 Optional Class Methods
|public static <T> Optional<T> empty()||This method returns an empty Optional object. No value is present for this Optional.|
|public static <T> Optional<T> of(T value)||This method returns an Optional with the specified value that is not null.|
|public static <T> Optional<T> ofNullable(T value)||This method returns an Optional describing the specified value if the value is non-null; otherwise, it returns an empty Optional.|
|public T get()||If a value is present in this Optional, then it returns the value. Otherwise, it throws NoSuchElementException.|
|public boolean isPresent()||This method returns a true value if there is a value present. Otherwise, it returns false.|
|public void ifPresent(Consumer<? super T> consumer)||If a value is present, then the consumer with the provided value is invoked. Otherwise, it does nothing.|
|public Optional<T> filter(Predicate<? super T> predicate)||If a value is present and it also matches the given predicate, then it returns an Optional describing the value. Otherwise, it returns an empty Optional.|
|public <U> Optional<U> map(Function<? super T,? extends U> mapper)||If a value is present, then the mapping function is applied, and if the result is not a null value, then it returns an Optional describing the result. Otherwise, it returns an empty Optional.|
|public <U> Optional<U> flatMap(Function<? super T,Optional<U> mapper)||If the value is present, then it applies the provided Optional-bearing mapping function to it and it returns that result. Otherwise, it returns an empty Optional.|
|public T orElse(T other)||This method returns the value if present; otherwise, it returns other.|
|public T orElseGet(Supplier<? extends T> other)||This method returns the value if present. Otherwise, it invokes other and returns the result of the invocation.|
|public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X extends Throwable||If the value is present, this method returns the contained value. Otherwise, it throws an exception to be created by the provided supplier.|
|public boolean equals(Object obj)||This method is used for indicating whether some other object is “equal to” this Optional or not.|
|public int hashCode()||This method returns the hash code value of the present value if it exists. Otherwise, it returns 0 (zero) .|
|public String toString()||This method is simply used to return a non-empty string representation of the Optional, which is suitable for debugging.|
Creating a Java 8 Optional Object
In this section, we are going to look at the different ways we can create the Java 8 Optional object:
1. Create an empty Optional object
The code below shows how to create an Optional object that has a null value. It simply describes the absence of a value.
2. Create an Optional object with a non-null value
The code below shows how to create an Optional object that has a non-null value.
It is important to note that if null is supplied to the argument of
Optional.of(), then it will throw the NullPointerException immediately and will not allow you to create the Optional object.
3. Create an Optional object with a value that can be both null and non-null
The code below shows how to create an Optional object that is allowed to have both null and non-null values.
If a non-null value is passed in
Optional.ofNullable(), then it will return the Optional containing the specified value. Otherwise, it just returns an empty Optional.
Checking the Presence of a Value in Java 8 Optional Object
Now, let's learn the different ways to check the presence of a value in the Java 8 Optional object through different methods:
isPresent() returns the value true in case the id of the Optional objects contains a non-null value. Otherwise, it returns a false value.
In the method
ifPresent(), we pass the Consumer function. That Consumer function will only be executed if a value is present in the Optional object.
If Optional is empty, then it does nothing:
In the code above, we have supplied the lambda function as the parameter of the
Retrieving the Value From Java 8 Optional Object Using get() Method
get() method of Optional is simply used to return a value from the Optional object. Suppose the value is not present, then it throws the exception NoSuchElementException.
In the case of the absence of a value, it throws an exception, so it is recommended that before using the
get() method, we should first check if the value is present or not.
Returning the Default Value From Java 8 Optional Object Using orElse() Method
orElse() is used to return a default value if the Optional object is empty.
See the example below:
Now, write the above logic using Java 8 Optional’s
Returning the Default Value From Java 8 Optional Object Using orElseGet() Method
As we learned, the method
orElse() returns one default value directly in case the Optional object is empty, but the
orElseGet() method accepts a Supplier and that Supplier is invoked when Optional is empty.
The result that is returned by the Supplier becomes the default value for Optional.
Throw an Exception if the Value Is Not Present in Java 8 Optional
orElseThrow() method is used for throwing an exception if the Optional object is empty.
It can be used in the scenario where the object for the specified request parameter does not exist in the REST API. You can use this method to throw custom exceptions like
Filter the Values Using Filter() Method of Optional
Suppose you have an Optional object of an Employee. Now, you are checking for the gender of the employee and calling a function correspondingly.
Below is the old approach for doing so:
Now, let us see how can we use Optional filter to achieve this:
filter() method takes a predicate as a parameter. In case the Optional is containing a non-null value and the value matches the provided predicate, then this method returns an Optional containing that value.
Otherwise, this method returns an empty Optional.
Extract and Transform Values Using map()
Suppose we have a scenario where we want to extract the address of an employee and also want to print its location depending upon a specified condition.
Consider the below example:
We have the
getAddress()method in our
Employee class :
Below is the typical approach to achieve the requested scenario:
Now see how we can use the
map() method of Optional to achieve the same results:
The above code, in comparison to the previous approach, is well readable, concise, and efficient.
Let’s understand the code in greater detail:
In the above code snippets, the method
map() is returning an empty Optional in one of the following cases:
- If the employee is not present in
- If the employee is present but the method
Otherwise, it simply returns an Optional<Address> that contains the employee address.
Cascading Optionals Using flatMap()
Now, let us again consider the above example related to the map() method.
You can see even if the Employee address can be null, then why are we not returning the Optional<Address> instead of a simple Address extracted using the
It will be incorrect as we will have a problem in the following line of code if we return the Optional<Address>:
Now, the method
getAddress() is returning
Optional<Address>, so the return type of
This is further demonstrated below:
Now, we have nested Optional and we don’t want that, so we can now use the
flatMap() method to solve this problem:
Please note that If your mapping function is returning an Optional, then use
map()to get the flattened result from your Optional object.
We have learned what Java 8 Optional is, its advantages, and problems solved by using Optional in Java. Additionally, we were able to better understand different methods of Java 8 Optional by looking at some illustrative examples.
Thanks for reading!
Published at DZone with permission of Shatakshi Dixit . See the original article here.
Opinions expressed by DZone contributors are their own.