Java 8 Optional Class

Daily Debug
Code Like A Girl
Published in
4 min readDec 19, 2024

Introduction

Every Java developer, at some point, has encountered a NullPointerException while developing an application. While it's often seen as a straightforward exception that can be avoided, as applications grow in size and complexity, it becomes increasingly difficult to pinpoint the exact cause of the issue. To address this challenge, Java 8 introduced the Optional class, designed to help developers handle null values more gracefully and reduce the likelihood of encountering NullPointerException.

Java Optional Class

How Optional helped me write better code

Avoiding NullPointerException

Primary use of Optional is to prevent NullPointerException, By using Optional you can avoid directly working with Null Values.

Clear Intent

  • One of the first things I encountered when I started using Optional was its ability to protect the code from the notorious NullPointerException.
  • I remember working on a legacy project where there was lot of code checking for null values, and it was getting cumbersome.
  • We decided to refactor some of the methods to return Optional instead of nullable types. Almost immediately, we noticed there was fewer NullPointerException errors, and the code became cleaner and more predictable. Instead of doing multiple null checks, we used methods like ifPresent() to ensure that we only acted on values that were actually present.
  • Optional helps to set clear intent of the code, Instead of returning Null to indicate that the value is absent you can return Optional.empty() to indicate that no value is present

Functional Style Methods

When I first started exploring functional programming concepts in Java, Optional was a gateway to those ideas. I was especially drawn to methods like map(), filter(), and ifPresent(), which allowed me to write more concise and expressive code.

Creating an optional object

There are three methods which we can use to create Optional Object

  1. Empty Optional — If we want to create optional with no value
 Optional<String> strEmptyOptional = Optional.empty();

2. Of (Non-null value): If you have a non-null value and you want to create an Optiona

Optional<String> nonNullOptional = Optional.of("Hello");

3. OfNullable (May be null): If the value may be null, use Optional.ofNullable(). It will return an empty Optional if the value is null, otherwise, it returns an Optional with the value:

Optional<String> nullableOptional = Optional.ofNullable(someString);

Methods in Optional

Here are some commonly used methods in optional —

isPresent(): Checks if the Optional contains a non-null value.

Optional<String> optional = Optional.of("Hello");
if (optional.isPresent()) {
System.out.println("Value: " + optional.get());
}

ifPresent(): Executes a given action if the value is present (i.e., non-null). This is useful for side-effects (e.g., logging or updating the UI).

optional.ifPresent(value -> System.out.println("Value: " + value));

get(): Returns the value if present. Note: Calling get() on an empty Optional will throw a NoSuchElementException, so use it cautiously.

String value = optional.get();

orElse(): Returns the value if present, or a default value if absent.

String value = optional.orElse("Default Value");

orElseGet(): Similar to orElse(), but the default value is provided by a supplier (a lazy evaluation).

String value = optional.orElseGet(() -> "Default Value");

orElseThrow(): Returns the value if present, or throws a specified exception if absent.

String value = optional.orElseThrow(() -> new IllegalArgumentException("Value not present"));

map(): Transforms the value inside the Optional if it’s present, or returns an empty Optional if absent. This is useful for chaining transformations.

Optional<String> upperCaseValue = optional.map(String::toUpperCase);

filter(): Filters the value inside the Optional based on a condition. If the value does not meet the condition, an empty Optional is returned.

Optional<String> filteredValue = optional.filter(s -> s.length() > 5);

flatMap(): Similar to map(), but the function passed to flatMap() must return an Optional itself. This is useful when working with nested Optional values.

Optional<Integer> length = optional.flatMap(s -> Optional.of(s.length()));

Example of Optional to avoid NullPointerException

import java.util.Optional;

public class OptionalExample {
public static void main(String[] args) {
String name = null;

// Creating an Optional object that may contain a null value
Optional<String> optionalName = Optional.ofNullable(name);

// Using ifPresent() to check if value is present
optionalName.ifPresent(value -> System.out.println("Name: " + value));

// Using orElse() to provide a default value when value is absent
String result = optionalName.orElse("Default Name");
System.out.println(result); // Output: Default Name

// Using orElseThrow() to throw an exception if value is absent
try {
String value = optionalName.orElseThrow(() -> new IllegalArgumentException("Name is missing"));
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage()); // Output: Name is missing
}

// Using map() to transform the value inside the Optional
Optional<String> upperCaseName = optionalName.map(String::toUpperCase);
System.out.println(upperCaseName.orElse("No Name")); // Output: No Name (because name is null)
}
}

When Not to Use Optional

While Optional is a powerful tool, it is not always the right solution. Here are some cases where Optional might not be the best choice:

  1. For fields in entities or POJOs: Avoid using Optional for fields in entities or JavaBeans because it introduces unnecessary complexity in data models, which are often serialized or deserialized.
  2. In collections or streams: You shouldn’t use Optional as a wrapper for values in collections (e.g., List<Optional<T>>). Instead, use Optional when dealing with a single value or method return.
  3. Performance Considerations: If performance is critical, creating an Optional could introduce overhead. If null values are common in your domain, consider other design patterns (e.g., Null Object pattern) or use null checks directly.

Conclusion

Optional in Java is a great way to handle optional values explicitly, avoiding null-related issues and making your code more robust and readable. However, it should be used thoughtfully in appropriate situations, especially in method return types, where the absence of a value makes sense.

Stay Tuned and Happy Learning :)

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in Code Like A Girl

Welcome to Code Like A Girl, a space that celebrates redefining society's perceptions of women in technology. Share your story with us!

Written by Daily Debug

I am software engineer, Technical Content Writer, here to help you learn and share my insights on various tech topics.

Responses (1)

What are your thoughts?

I dislike the Optional class in Java. It is a very clunky way to handle nullability.
I prefer the way e.g. Kotlin and C# (and other languages) have implemented it.
Kotlin:

--