Over a million developers have joined DZone.

Making Code Readable With Optional

See how you can take advantage of the Optional class to improve the readability of your code.

· Java Zone

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

Working with the ZAP API recently I found myself writing code like this:


The API was constructed around the idea of key/value pairs, and often returned objects that had to be cast to more specific types, which forces you to add a lot of boilerplate code for simple tasks like getting the ID of the last scan. Still, code like this was getting out of hand.

One of the problems with statements like this (beyond the obvious of trying to do too much with a single line of code) is that instead of reading the code left to right, you have to read it from the middle out. I have always found nested method calls to be far less readable than a fluent chaining of methods for this very reason.

So is there a better way? In this case, the Optional class comes to the rescue. That one single, ugly line of code can be broken down into a much more fluent sequence of calls like so:

  .map(e -> (ApiResponseList)e)
  .map(e -> (ApiResponseSet)e)
  .map(e -> e.getAttribute("id"));

The map method allows us to progressively transform the objects we are working with through a series of clear steps. The code is much more readable, and actually benefits from a degree of protection from Null Pointer Exceptions because the map method will not attempt to work with a null. But we can make it better.

Any of those casts could fail, throwing an exception, so let’s borrow a concept from C#’s as operator, which will cast an object or return null if the cast was invalid.

public class CastUtils {
  public static <T> T as(Class<T> t, Object o) {
     return t.isInstance(o) ? t.cast(o) : null;

Now our code looks like this:

  .map(e -> CastUtils::as(ApiResponseList.class, e))
  .map(e -> CastUtils::as(ApiResponseSet.class, e))
  .map(e -> e.getAttribute("id"));

Now if any cast fails or any method returns null, the end result is an empty Optional rather than an exception. This is ideal because if I can’t get the last item’s ID, I don’t really care which point in the transformation failed, I just need to know that the information I want is not available.

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.


Published at DZone with permission of Matthew Casperson, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}