How to use Optional values on Java/Kotlin and Android

How to use Optional values on Java/Kotlin and Android

Optional values are very useful but unfortunately not available in Android (Java and Kotlin Standard Library) so in this post we will see how we can make use of them presenting different practical use case scenarios.

“A clever person SOLVES a problem, a wise person AVOIDS it.”

Introduction

First of all, this is not a new topic and a lot has already been discussed about it.

With that being said, in this article, I want to explain what Optional<T> is, expose a few use case scenarios, compare different alternatives (in other languages) and finally, I do want to show you how we can effectively make use of the (inexistent till now) Optional<T> API on Android (although this can be applied to any Java/Kotlin project, specially those ones targeting Java 7 and above).

To get started, let me quote this (retrieved from the Official Java 8 documentation:

A wise man once said you are not a real Java programmer until you have dealt with a null pointer exception, which is the source of many problems because it is often used to denote the absence of a value.

Although this statement is true and Java 8 documentation refers to the use of Optional<T> as NullPointerException saver, in my opinion, it is not only useful to minimize the impact of NPE, but to create more meaningful and readable APIs.

Additionally, it is well known that not being careful when using null values can lead to a variety of bugs, and for instance, null is ambiguos, and we do not always have a clear meaning for it: is it an inexistent value? For example, when a Map.get() method returns null, can mean the value is absent or the value is present and null.

We will try to answer to these questions in this little journey. Let’s get our hands dirty!

What is an Optional?

First definition from Java 8 documentation:

Optional object is used to represent null with absent value. It provides various utility methods to facilitate code to handle values as ‘available’ or ‘not available’ instead of checking null values.

This is another similar definition from the Official Guava documentation:

An immutable object that may contain a non-null reference to another object. Each instance of this type either contains a non-null reference, or contains nothing (in which case we say that the reference is “absent”); it is never said to “contain null”. A non-null Optional<T> reference can be used as a replacement for a nullable T reference. It allows you to represent “a T that must be present” and a “a T that might be absent” as two distinct types in your program, which can aid clarity.

In a nutshell, the Optional Type API provides a container object which is used to contain not-null objects.

Let’s see a quick example so you get a better understanding of what I am talking about:

Optional<Integer> possible = Optional.of(5);
possible.isPresent();   // returns true
possible.get();         // returns 5

As you can see, we are wrapping an object of type <T> inside an Optional<T> so we can check its existence later. In other words, Optional<T> forces you to care about the value, since in order to retrieve it, you have to call the get() method (as a good practice always check the presence of it first or return a default value). Just to be clear, we are using Guava’s Optional<T> here.

Don’t worry much if you still don’t understand, we will explore more afterwards.

Java 8, Scala, Groovy and Kotlin Optional/Option APIs

As I mentioned above, in this article we will focus on Guava Optional<T>, although it is worth to give a quick view to what other programming languages have to offer.

Let’s have a look at what Groovy and Kotlin bring up.

These 2 languages offer similar approaches for null safety:Elvis Operator’.

They have added some syntactic sugar and syntax look similar in both of them.

Let’s check this piece of Kotlin code: when we have a nullable reference r, we can say “if r is not null, use it, otherwise use some non-null value x”:

val l: Int = if (b != null) b.length else -1

Along with the complete if-expression, this can be expressed with the Elvis Operator, written ?::

val l = b?.length ?: -1

If the expression to the left of ?: is not null, the elvis operator returns it, otherwise it returns the expression to the right. Note that the right-hand side expression is evaluated only if the left-hand side is null.

For the record, Kotlin also has a check for null conditions at compilation time.

You can dive deeper by checking the official documentation and, by the way I’m not neither a Groovy nor Kotlin guy at this point in time, so I will leave this to the experts :).

On both Java 8 and Scala sides we find a monadic approach for Optional<T> (Java) and Option[T] (Scala), allowing us to use flatMap(), map(), etc. This means we can compose data stream using Optional<T> in a Functional Programming style.

Kotlin also offers an OptionIF<T> monad with the same purpose.

Let’s have a quick look at this Scala example from Sean Parsons for a better understanding:

case class Player(name: String)

def lookupPlayer(id: Int): Option[Player] = {
  if (id == 1) Some(new Player("Sean"))
  else if(id == 2) Some(new Player("Greg"))
  else None
}

def lookupScore(player: Player): Option[Int] = {
  if (player.name == "Sean") Some(1000000) else None
}

println(lookupPlayer(1).map(lookupScore))  // Some(Some(1000000))
println(lookupPlayer(2).map(lookupScore))  // Some(None)
println(lookupPlayer(3).map(lookupScore))  // None

println(lookupPlayer(1).flatMap(lookupScore))  // Some(1000000)
println(lookupPlayer(2).flatMap(lookupScore))  // None
println(lookupPlayer(3).flatMap(lookupScore))  // None

Last but not least we have Optional<T> from Guava. In favor of it, let’s say that its simplified API fits perfectly the Java 7 model: there is only one way to use it which is the imperative one, since in fact, was developed for Java that lacks first-class functions.

I guess so far so good, but there is NO Android Java 7 sample code… Ok, you are right, but you will have to keep on reading, so be patient, there is more coming up.

Also if you are wondering whether in order to use it on Android you will have to compile Guava and its 20k methods, the answer is NO, there is an alternative to bring up Optional<T> to the game.

How can we use Optional<T> in Android?

First point to raise here is that we are stuck to Java 7 so there is no built-in Optional<T> and we have to aks for help to 3rd party libraries unfortunately…

Our first player is Guava, which for Android might not be a good catch, specially (as mentioned above) because of the 20k methods that brings up to your .apk (I’m pretty sure you have heard of 65k method limit issue ;)).

The second option is to use Arrow, which is a lightweight open source library I created by gathering and including useful stuff I use in my day to day Android development plus some other utilities I wrote myself and with the help of my team, such as annotations for code decoration, etc. You can check the project, documentation and features on Github.

One thing to remark and shout loudly is that ALL CREDITS GO TO THE CREATORS OF THESE AWESOME APIs.

How do we create Optional<T>?

The Optional<T> API is pretty straightforward:

Optional Android Java API

Here are the Optional<T> query methods:

Optional Android Java Query

It is time for code samples and use cases so please do not leave the room yet.

Case scenario #1

This is a well known historical Tony Hoare’s phrase when he created the null reference:

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement.

public class Car {
  private final String brand;
  private final String model;
  private final String registrationNumber;

  public Car(String brand, String model, String registrationNumber) {
    this.brand = brand;
    this.model = model;
    this.registrationNumber = registrationNumber;
  }

  public String information() {
    final StringBuilder builder = new StringBuilder();
    builder.append("Model: ").append(model);
    builder.append("Brand: ").append(brand);
    if (registrationNumber != null) {
      builder.append("Registration Number: ").append(registrationNumber);
    }
    return builder.toString();
  }
}

The main issue with the following code is that relies on a null reference to indicate the absence of a registration number (a bad practice), so we can fix this by using Optional<T> and we print according whether or not the value is present:

public class Car {
  ...
  private final Optional<String> registrationNumber;

  public Car(String brand, String model, String registrationNumber) {
    ...
    this.registrationNumber = Optional.fromNullable(registrationNumber);
  }

  public String information() {
  ...
    if (registrationNumber.isPresent()) {
      builder.append("Registration Number: ").append(registrationNumber.get());
    }
    return builder.toString();
  }
}

The most obvious use case is for avoiding meaningless nulls. Check full class implementation on Github. Let’s move forward to the next scenario.

Case scenario #2

Let’s say we need to parse a JSON file coming from an API response (something very common in Mobile Development).

In this case we can use Optional<T> in our Entity ir order to force the client to care about the existence of the value before using or doing anything with it.

Check out “nickname” field and getter in the following sample code:

public class User {
  @SerializedName("id")
  private int userId;

  @SerializedName("full_name")
  private String fullname;

  @SerializedName("nickname")
  private String nickname;

  public int id() {
    return userId;
  }

  public String fullname() {
    return fullname;
  }

  public Optional<String> nickname() {
    return Optional.fromNullable(nickname);
  }
}

Complete sample class on Github.

Case scenario #3

This is another use case we usually stumble upon at @SoundCloud in our Android application.

When we need to construct our feed or any list of items and show them at UI level (presentation models), we have items coming from different data sources, and some of them might be Optional<T>, like for example, a Facebook invitation, a promoted track, etc.

Check this little example, which tries to emulate the above situation in a very simplified way (for learning purpose) using RxJava:

public class Sample {

  public static final Func1<Optional<List<String>>, Observable<List<String>>> TO_AD_ITEM =
      ads -> ads.isPresent()
          ? Observable.just(ads.get())
          : Observable.just(Collections.<String>emptyList());

  public static final Func1<List<String>, Boolean> EMPTY_ELEMENTS = ads -> !ads.isEmpty();

  public Observable<List<String>> feed() {
    return ads()
        .flatMap(TO_AD_ITEM)
        .filter(EMPTY_ELEMENTS)
        .concatWith(tracks())
        .observeOn(Schedulers.immediate());
  }

  private Observable<Optional<List<String>>> ads() {
    return Observable.just(Optional.fromNullable(
      Collections.singletonList("This is and Ad")));
  }

  private Observable<List<String>> tracks() {
    return Observable.just(
      Arrays.asList("IronMan Song", "Wolverine Song", "Batman Sound"));
  }
}

The most important part here is that when we combine both Observables<T> (tracks() and ads() method) we use flatMap() and filter() operators to determine whether or not we are gonna emit ads and for instance, display them at UI level (I’m using Java 8 lambdas here to make the code more readable):

public static final Func1<Optional<List<String>>, Observable<List<String>>> TO_AD_ITEM =
      ads -> ads.isPresent()
          ? Observable.just(ads.get())
          : Observable.just(Collections.<String>emptyList());

public static final Func1<List<String>, Boolean> EMPTY_ELEMENTS = ads -> !ads.isEmpty();

Check out the full implementation on Github.

Conclusion

To wrap up, in software development there are no silver bullets and as programmers we tend to overthink and overuse things so don’t pollute your code with Optional<T> everywhere, use them carefully where it makes sense.

Also let me quote Joshua Bloch in his talk ‘How to Design a Good API and Why it Matters’:

APIs should be easy to use and hard to misuse: It should be easy to do simple things; possible to do complex things; and impossible, or at least difficult, to do wrong things.

I completely agree with this, and from an API design standpoint, Optional<T> is a good example of a well design API: it will help you address and protect from NullPointerException issues (although not fully eliminate them), write concise and readable code and additionally will provide a more meaningful codebase.

Sample Code

You can find all the sample code in a Github repo I created for this purpose:

Also visit the Arrow project repo to make use of Optional<T> in Android:

References