In this Java 8 Optional Tutorial you will learn How to avoid Nulls and Null Pointer Exceptions and avoid Null Checks using Java 8 Optional.
What is Null and NullPointerException ?
Java by-default assigns null to uninitialised object reference variables. In other words, when you declare reference variables, and do not initialise them, java assign them a special value called as null.
{ String string1; String string2 =
public
class
TestClass
null
;public
static
void
main
(String[] a)
{ TestClass testClass =new
TestClass(); System.out.println(testClass.string1); System.out.println(testClass.string2); } }Code language:
Java
(
java
)
Why NullPointerException ?
In Java the reference variables are not objects. But, reference variables are just handle to the objects. Although you use reference variables to access a member, you actually access them through objects. Hence, when you try to access a member on an un-initialised reference variable, you get a NullPointerException.
In Java a program can assign a reference variable to an object at runtime. Therefore it is not possible at compilation time to know if a certain reference is going to be null. Hence the NullPointerExceptions are runtime exceptions and difficult to foresee.
For instance, you are writing an UserService, whose getUsers method returns List of Users. The User and the referred Address class look like below.
{
public
class
User
private
String name;private
String lastName;private
Address address; ... }class
Address
{private
String address;private
String suburb;private
String state; ... }Code language:
Java
(
java
)
Now, the consumer of UserService wants to print the state of first User from the list. For that, it will extract the nested objects.
List<User> users = service.getUsers(); System.out.println(
"State is "
+ users.get(0
).getAddress().getState());Code language:
Java
(
java
)
Here, you have introduced possibility of NullPointerExceptions. Below are the possibilities:
- Entire list is null.
- First User from the list is null.
- Users Address is null.
In any of the cases your code is going to throw a NullPointerException. The exception can be avoided by adding Null checks.
Null Checks to avoid NullPointerException
To avoid the NullPointerExceptions, you need to add null checks in your code. For example, refer to the modified example below
if
(users !=null
) { User user = users.get(0
);if
(user !=null
) { Address address = user.getAddress();if
(address !=null
) { String state = address.getState();if
(state !=null
) { System.out.println("State is "
+ state); } } } }Code language:
Java
(
java
)
Finally, we have avoided all the potential NullPointerExceptions and the code is now safe. However, that made the method ugly. Moreover, think about the case where there are more nested objects like this.
What is Optional ?
Java 8 introduced an Optional class which is a nicer way to avoid NullPointerExceptions. You can use Optional to encapsulate the potential null values and pass or return it safely without worrying about the exception.
Without Optional, when a method signature has return type of certain object. The user often tend to assert the existence of the object. Hence, the possibility of null is often ignored.
The Optional, clearly indicates method behaviour. For example, below method signature clearly indicates that it may or may not return the list of Users.
;
Optional<List<User>> getUsers();
List<User>
getUsers
()
Code language:
Java
(
java
)
Also, the Optional improves documentation and makes more sense. For example, you have seen our User class in the above sections. It doesn’t indicate that the Address is an optional field and can be left blank. For instance, we will add Optional in the example and it will be more clear.
{
public
class
User
private
String name;private
String lastName;private
Optional<Address> address; ... }Code language:
Java
(
java
)
How to use Optional ?
Now, let’s see how can you use Optional to check if the contained object is null or not and what actions we can take in either cases.
Get Value
The get
method simply returns the encapsulated object from optional. In this case, no null check is done and the optional returns the contained value as is.
Optional<Address> optAddress = user.getAddress(); Address address = optAddress.get();
Code language:
Java
(
java
)
Get if Object is Not Null, else Throw Exception
The method orElseThrow
is more convient and safe method to use. It returns the object value if the object is not null. However, if the object is null it throws the specified exception.
Optional<Address> optAddress = user.getAddress(); Address address = optAddress.orElseThrow(UserNotFoundException::
new
)Code language:
Java
(
java
)
Note: the UserNotFoundException::new
is an example of Constructor Reference.
Get if Object is Not Null, else return default
The method orElse
is one more interesting method of Optional. It returns the contained value if it is not null. Otherwise it returns the given default value.
Address defaultAddress =
new
Address (....); Optional<Address> optAddress = user.getAddress(); Address address = optAddress.orElse(defaultAddress);Code language:
Java
(
java
)
Check if it is Not Null
The isPresent
is a simple boolean check to see if the contained object is null.
Address address;
if
(optAddress.isPresent){ address = optAddress.get(); }Code language:
Java
(
java
)
Consume if it is not Null
The ifPresent
method passes the value to Consumer Function in the form of Lambda Expression.
Optional<Address> optAddress = user.getAddress(); optAddress.ifPresent(System.out::println);
Code language:
Java
(
java
)
How to create Optional instance ?
Till now you learnt, how to use Optional. Now, in this section we will see what are the ways to create and Optional instance.
Empty Optional
There is a static empty
method in Optional class that creates an empty optional. For example, if a method has nothing to return it can return an empty optional instance.
return
Optional.empty();Code language:
Java
(
java
)
Optional of Not Null value
If you want to assert that the object to be placed in the Optional is not-null, you can use the static of
method. You will get NullPointerException if you try to put a null value in optional using of()
.
Optional.of(notNullUserList); Optional.of(
new
User(...));Code language:
Java
(
java
)
Optional of Nullable value
Finally, if you want to return a nullable value use the static ofNullable
method on Optional.
Optional.ofNullable(user); Optional.ofNullable(
null
);Code language:
Java
(
java
)
Summary
This was an Introduction to Java 8 Optional. To sum up below are the points you learnt.
- The NullPointerExceptions in Java occur at runtime and is unexpected.
- Null checks avoid NullPointerExceptions. However, the code looks ugly.
- The Optional is an object container provided by Java 8 which encapsulates the object returned by method.
- Optional has methods to safely access the contained object. Hence avoid null checks and NullPointerExceptions.
- There are various ways of creating Optional instance and accessing the contained value.
Benefits of Using Optional
- Avoids Null checks and NullPointerExceptions.
- Clearly indicates method behaviour (what the method returns).
- Improves documentation. For example, explicitly indicates optional fields in an object.