
How to use and how not to use Optional in Java
If you are bored by null checking objects and want to make your code more readable, you should consider using Optional class. It is a container used to represent null with absent value.
Krzysztof Mazur |
29 Apr 2020
# How to use and how not to use Optional in Java
## Introduction
If you are bored by null checking objects and want to make your code more readable, you should consider using Optional class. It is a container used to represent null with absent value.
Old null-check
```java
if(house != null) {
doSomething(house);
}
```
Optional newbie null-check
```java
Optional maybeHouse = Optional.ofNullable(house);
if(maybeHouse.isPresent()) {
doSomething(maybeHouse.get());
}
```
## How to use Optional correctly
It is almost the same as "old" null-check and it is an anti-pattern.
- ofNullable(T value) Returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional.
- isPresent() Return true if there is a value present, otherwise false.
- get() If a value is present in this Optional, returns the value, otherwise throws NoSuchElementException.
And the proper way
```java
Optional maybeHouse = Optional.ofNullable(house);
maybeHouse.ifPresent(this::doSomething);
```
You can use method reference or lambda to make code more readable
- isPresent([Consumer](https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html) super [T](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html)>; consumer) If a value is present, invoke the specified consumer with the value, otherwise do nothing.
**Default value**
The _Optional_ class provides APIs for returning the value of the object or a default value if the object is empty.
```java
Table table1 = null;
Table table2 = new Table("green");
Table result = Optional.ofNullable(table1).orElse(table2);
```
So if first object is null, then return second object instead. If first object isn't null so default value will be ignored
- orElse([T](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html) other) Return the value if present, otherwise return ther.
You can also throw exception if object is null
```java
Table table1 = null;
Table result = Optional.ofNullable(table1).orElseThrow(IllegalStateException::new);
```
- orElseThrow([Supplier](https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html) extends X> exceptionSupplier) Return the contained value, if present, otherwise throw an exception to be created by the provided supplier.
**Filter**
Usually you have to check property of your nullable object and then came filter method
For example you want to know if table1 is black
```java
Table table1 = new Table("green");
Boolean isBlueTable = Optional.ofNullable(table1)
.filter(e -> e.getColour() == "black")
.isPresent();
```
- filter([Predicate](https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html) super [T](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html)> predicate) If a value is present, and the value matches the given predicate, return an Optional describing the value, otherwise return an empty Optional.
**FlatMap**
Now let's take a look at the previous java version cascading problem
```java
String tableColour = house.getRoom().getTable().getColour();
```
To take a colour of a table which is in the room in your house, you have to check if there is not any null on your way to prevent a NullPointerException
```java
String tableColour;
if(house != null) {
Room room = house.getRoom();
if(room != null) {
Table table = room.getTable();
if(table != null) {
tableColour = table.getColour();
}
}
}
```
Now your code is safe but due to the nested null checks it is not clean and looks ugly. Optional gives you alternative and clean way to handle multiple null checks
First of all update your class to make use of Optional
```java
class House {
Optional<Room> room;
public Optional<Room> getRoom() {
return room;
}
}
class Room {
Optional<Table> table;
public Optional<Table> getTable() {
return table;
}
}
class Table {
String colour;
public String getColour() {
return colour;
}
...
```
After refactoring you don't need to use nested null check and it is more clear that for example Room can have a table, but it is not necessary.
Let take a look at the new way of null checking using flatmap and map
```java
String tableColour = Optional.ofNullable(house)
.flatMap(House::getRoom)
.flatMap(Room::getTable)
.map(Table::getColour)
.orElse("black");
```
Code is clean and more readable
- map([Function](https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html)< super [T](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html),? 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.
- flatMap([Function](https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html) super [T](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html),[Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html)> mapper) If a value is present, apply the provided Optional-bearing mapping function to it, return that result, otherwise return an empty Optional.
## Conclusion
To sum up Optional is one of the most useful features from Java 8+ which will help you everywhere you have to stand against NullPointerException
Bibliography:
[https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html)
Krzysztof Mazur
Did you like this article?
4,5 / 34