Reduce NullPointerExceptions with Optional in Java – CodersTea

Hey, Tea Lovers! Today we will talk about the Optional class in Java 8. But before that, Did you know that Tony Hoare, The inventor of the null reference, has said that the null reference is his “Billion Dollar Mistake”? Since NullPointerException is the most common and frequently appeared error compared to others, especially for Java developers.

You can follow me on social media via @coderstea on Twitter, Linkedin, Facebook, or Instagram. We also share high-quality videos about programming on our YouTube channel. You can also publish your post on CodersTea, just share your thought on Contact Us or let us know in the comments.

I have seen people wrapping each code block in a try-catch to handle this sneaky fool. That’s how much we are scared of this exception.

In most of the cases, a simple check is done like, obj !== null, Objects.isNull(obj). But in modern Java, from Java8, we have a new approach to handle the null object, or I would say, protecting us from NullPointerException. And that’s called Optional.

What is Optional In Java 8

Optional.java is a class in java.util the package that, as the name suggests, holds the optional value. This means, the value is optional and may or may not be present. It encapsulates your object and with multiple methods, it gives you the power to retrieve the object in various manners.

Optional has been introduced in Java8 and is used in various parts since then. If you look at the Stream API, it has used Optional in many cases. Spring JPA also returns Optional values for a single object. And you can also use it in your code. Let us look at how.

Create an Optional in Java

To create an Optional, you just have to use the Optional’s static method(s). It depends on what kind of object you are encapsulating. Let’s see them.

If your object is not null, then you can use Optional.of(obj). It returns the Optional of the object. But if your object is null, it will give you a NullPointerException. So you have to use Optional.ofNullable(obj) which will return an empty Optional. You can directly return an empty Optional with Optional.empty().

Optional<

String

> nonEmptyOptional = Optional.of(

"Not null"

); System.out.println(nonEmptyOptional.isPresent()); Optional<

String

> nullObject = Optional.ofNullable(

null

); System.out.println(nullObject.isPresent()); Optional<

String

> emptyOptional = Optional.empty(); System.out.println(emptyOptional.isEmpty());

Code language:

JavaScript

(

javascript

)

Check Optional State

In the previous block, I used isPresent() for checking whether the optional object holds any value or is it empty. It will return true if it holds value i.e not a null object, otherwise, it returns false for empty Optionals. It is similar to checking whether the object is null or not. You can also use isEmpty(), introduced in Java 11, which is exactly the opposite of isPresent(). For empty Optional, it will return true otherwise false.

if

(nonEmptyOptional.isPresent()){ System.out.println(

"The value is present"

); }

if

(nullObject.isEmpty()){ System.out.println(

"No value is not present"

); }

Code language:

JavaScript

(

javascript

)

Get the Value

OK, so we encapsulated the object into Optional. I have also checked for it. But How do I get the original value? Well, you can do so by calling get(). It will return the object from Optional. But beware, you shouldn’t be using the get() directly. Since it returns the value directly and if it has a null value it will throw an exception. So better to be used with isPresent() than go on with the get().

if

(nonEmptyOptional.isPresent()) { System.out.println(

"The value "

+ nonEmptyOptional.get()); }

if

(!nullObject.isPresent()) { System.out.println(

"No value is not present"

); }

Code language:

JavaScript

(

javascript

)

The above code, is OK but not so advantageous, we could have done it with a simple null check, right? There is a better way of handling things. There are quite a few depending on your requirement.

ifPresent(Consumer)

It is the combination of isPresent() and get(), but in a functional way. As the name suggests, do this if the value is present. It takes a Consumer as input. The Consumer will only be called if the value is present i.e non-null object. More about the Consumer here.

Optional<String> codersTea = Optional.of(

"coderstea.in"

); nonEmptyOptional.ifPresent(site -> System.out.println(

"World's best website is "

+ site)); Optional<String>

empty

= Optional.

empty

();

empty

.ifPresent(x -> System.out.println(

"No this will not run."

));

Code language:

PHP

(

php

)

Get Default Value if Empty

Now, what if you want to assign a default value if the object is null? You can do so by calling orElse(defaultObj). This way, if the Optional is empty defaultObj will be returned otherwise, the original value will be returned.

Optional<

String

> empty = Optional.empty();

String

name = empty.orElse(

"Default Name"

);

String

name1 = Optional.of(

"CodersTea"

).orElse(

"Default Name"

);

Code language:

JavaScript

(

javascript

)

It’s a great approach, but the default object will be created every time you call the function regardless of empty optional. Since you are passing it as the value it is getting created eagerly. It is an unnecessary burden. Here’s how.

public

static

void

main(

String

[] args) { Optional<

String

> empty = Optional.empty();

String

name = empty.orElse(printAndReturnDefaultName());

String

name1 = Optional.of(

"CodersTea"

).orElse(printAndReturnDefaultName()); }

static

String

printAndReturnDefaultName(){ System.out.println(

"Default Name"

);

return

"Default Name"

; }

Code language:

JavaScript

(

javascript

)

Output:

Default

Name

Default

Name

Code language:

PHP

(

php

)

As you can see it is printed two times, even though it is needed for 1 time only. To overcome this, we can use the Functional Way. Here is how.

orElseGet(Supplier)

It takes in a Supplier as a parameter. Read more about Supplier in my post “Be More Functional with Java’s Functional Interfaces“. Since Functional programming is Lazy, It won’t be created until called. And that’s the major difference between orElse() which uses eager initialization of default object and orElseGet() which initializes lazily i.e when needed.

Optional<

String

> empty = Optional.empty();

String

name = empty.orElseGet(() -> printAndReturnDefaultName());

String

name1 = Optional.of(

"CodersTea"

).orElseGet(() -> printAndReturnDefaultName());

String

name2 = Optional.of(

"SuperHero"

).orElseGet(OptionalClass::printAndReturnDefaultName);

Code language:

JavaScript

(

javascript

)

Output:

Default

Name

Code language:

PHP

(

php

)

As you can see, it is called only once for empty Optional.

orElseThrow()

Sometimes you can’t take it anymore and it’s enough. No more null value or you will burst out. To take out that frustration you can use is orElseThrow(). Does it take a Supplier<? extends Throwable> as a parameter and if the optional is empty throws the given Exception. You can use it if you can’t proceed without a value or any condition where a null object is not tolerated.

Optional.

empty

().orElseThrow(() ->

new

Exception

(

"Provide me a Name, man"

)); Optional.ofNullable(

null

). orElseThrow(FileNotFoundException::new);

Code language:

PHP

(

php

)

Do More than Null Checks

Now that we have seen how it manages the null values let us see how it expands beyond null checks. Optional has more functions than listed above. Just like Stream API, you can create your pipeline with the Optional. The only difference is that Stream API works on Collection, while Optional is on the given Object. You can do the filter, map, flatMap, and many more. I have discussed this in my “Stream API: The Hero Without a Cape“. For now, I will go through the pipeline.

@Data @Builder

class

Employee

{

private

String name;

private

int age;

private

boolean isManager;

private

List

<Integer> tasksIds;

public

static

void main(String[] args) { Employee employee = Employee.builder() .age(

23

).name(

"Bob"

).isManager(

false

) .tasksIds(Arrays.asList(

1

,

2

,

3

,

4

)) .build(); int empGt20TaskCount = Optional.of(employee) .filter(e -> e.getAge() >

20

) .map(Employee::getTasksIds) .map(

List

::size) .orElse(

-1

); System.out.println(

"Employee with age over 20 and its task count is "

+ empGt20TaskCount); Employee manager = Employee.builder() .age(

23

).name(

"Bob"

).isManager(

true

) .tasksIds(Arrays.asList(

1

,

2

,

3

,

4

)) .build(); Optional.of(manager) .filter(e -> e.getAge() >

20

) .filter(Employee::isManager) .map(Employee::getTasksIds) .map(

List

::size) .ifPresent(tasks -> System.out.println(

"Manger is having"

+ tasks +

" tasks"

)); Optional.of(employee).filter(Employee::isManager).orElseThrow(() ->

new

Exception

(

"IT must be manager"

)); } }

Code language:

PHP

(

php

)

As you can see, the code has become more declarative, and Optional is providing more than just a null value check. By the way, if you are wondering what the @Data or @Builder is check out my previous post on Lombok “Say Good-Bye to Boilerplate Code with Lombok: Part 1-Installation” and “Say Good-Bye to Boilerplate Code with Lombok: Part 2-The Code“.

Conclusion of Optional in Java

I think I have pretty much covered the Optional for Java 8. If you use this class then you will have much more flexibility in handling null values and may greatly decrease the possibility of NullPointerException. And it goes beyond null checks and provides you with Functional Programming experience. Please let me know in the comments how did you like the post or want any improvement in the content.

The examples used in this post can be found on GitHub here or the full project here. 

See you in the next post. HAKUNA MATATA!!!

You can follow me on social media via @coderstea on Twitter, Linkedin, Facebook, or Instagram. We also share high-quality videos about programming on our YouTube channel. You can also publish your post on CodersTea, just share your thought on Contact Us or let us know in the comments.