DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report

Optional Anti-Patterns

Optionals have proven so useful that some devs have taken them out of their native habitat. Here are anti-patterns and code smells to avoid.

Przemyslaw Magda user avatar by
Przemyslaw Magda
·
Jul. 13, 17 · Tutorial
Like (45)
Save
Tweet
Share
56.89K Views

Join the DZone community and get the full member experience.

Join For Free

The Optional container was introduced with Java 8. Its main purpose is to handle cases when a return value might be missing. However, over time, developers started to use it not as it was intended. Let’s talk briefly about what it actually is and then move onto some anti-patterns.

How to Use It

Originally created for Stream operations to handle cases when values might be missing (and some default one could be provided). According to the documentation, Optional should be used as a return type. And that’s all. It's a neat solution for handling data that might be not present.

Anti-Pattern #1: Optional Types in Object Fields

Optionals cannot be used here because as they are not serializable (more about that later). Let’s describe the problem:

We have a class where one of the fields might be not present. Perfectly valid use case.

public class Car { 
  private List<Wheel> wheels;
  private Optional<Engine> engine;

  // getter and setter 
}


Unfortunately, due to the previously mentioned Optional limitations, our model class needs to be rewritten. Luckily, this situation could be solved by a getter method returning an Optional type from a nullable field, like in the code below:

public class Car { 
    private List<Wheel> wheels;
    private Engine engine;

    public Optional<Engine> getEngine() {
        return Optional.ofNullable(engine); 
    } 
}


Anti-Pattern #2: Collections of Optionals

Another use case you might run into is the Optional type in collections like:

private List<Optional<Wheel>> wheels;


This is simply a code smell. There is no need to have List of Optionals that might or might not have a value. We can have a smaller or even empty List of concrete objects instead.

Anti-Pattern #3: Optional as a Method Argument

Optional is a value-based class, thus it does not have any public constructors. We can create a new instance using static methods:

Optional.empty()
Optional.of(T value)
Optional.ofNullable(T value)


Using Optionals as arguments would make our method look like:

Long calculate(List<Optional<Long>> data)


Now let’s use this method:

List<Long> data = Arrays.asList(1L, 2L);
calculate(Optional.of(data));


Optional wraps objects with another level of abstraction, which, in that case, is simply extra boilerplate code. On the other hand, we have a cleaner solution without Optional.

List<Long> data = Arrays.asList(1L, 2L);
calculate(data);


Anti-Pattern #4: Trying to Serialize Optionals

Optionals were not designed to be serialized. Object serialization depends on object identity. If we take a look at the Javadocs, we can see that Optional was designed to be value-based:

"This is a value-based class; use of identity-sensitive operations (including reference equality (==), identity hash code, or synchronization) on instances of Optional may have unpredictable results and should be avoided" — from the Javadoc.

The reasoning as to why Optional became a value-based class in the first place was well-described by Stuart Mark at the Devoxx conference. Stuart Mark states that Optional will become serializable as a value type in the future thanks to Project Valhalla.

In case you really, really need to serialize Optional, you have to consider using different libraries, like Guava Optional or Vivr Optional.

Summary

In this short article, I tried to describe use cases where Optional anti-patterns arise with solutions to make them right. Like always, those rules are not written in stone, but it might be useful to at least be familiar with them.

Anti-pattern

Published at DZone with permission of Przemyslaw Magda. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • How To Build a Spring Boot GraalVM Image
  • Real-Time Analytics for IoT
  • What Is Advertised Kafka Address?
  • Top 5 Data Streaming Trends for 2023

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: