Skip to content

Instantly share code, notes, and snippets.

@vple
Last active June 11, 2018 15:55
Show Gist options
  • Save vple/cb28ee5302d9e635971ee73351c40e00 to your computer and use it in GitHub Desktop.
Save vple/cb28ee5302d9e635971ee73351c40e00 to your computer and use it in GitHub Desktop.

Optionals

Where To Use Optionals

Rule
Do not use Optional for constructor or method parameters.

Rule

Do not declare instance variables as Optional.

Suggestion

Use Optional for return types that can have no result.

Optional is intended to be a limited way for library methods to represent "no result" return types. It is not intended to be used as an all-purpose way to safely handle null or to be a complete shift away from using null.1

This is also supported by what we've seen with our usage of Optional. Used excessively, it feels cumbersome and awkward since objects end up being converted to or from Optional just to satisfy a type signature.

Within a class, you should use null to represent optional data. That data can be returned as an Optional to external callers.

WARNING

Single parameter methods returning Optional should either not expect null as an input or map null -> Optional.empty().

Otherwise, developers using such a method may run into unexpected behavior. For more on this, please see the related warning below.

How To Use Optionals

Rule

Use Optional.of over Optional.ofNullable if your argument cannot be null.

The two are the same from a code perspective, but differ when it comes to readability. Optional.of lets future developers know that the argument will not be null without them needing to read how that argument is computed.

Rule

Optional.get should not be used unless you know it is safe. Instead, use a method such as orElse or ifPresent.2

Suggestion Use Optional.map or Optional.flatMap to map an Optional value before unboxing it. This is in contrast to unboxing an Optional and then mapping it, since that requires explicitly dealing with null.

// SUGGESTED
Optional<Business> business = getBusiness();
Business parentBusiness = business.map(Business::getParentBusiness).orElse(null);
// ALTERNATIVE
Business business = getBusiness().orElse(null);
Business parentBusiness = null;
if (business != null) {
	parentBusiness = business.getParentBusiness();
}

WARNING

The functions passed in to Optional.map or Optional.flatMap should trivially handle null as an input.

To be specific, "trivially handle" means one of the following:

  • The function is never expected to receive a null input.
  • For Optional.map, the function maps null -> null.3
  • For Optional.flatMap, the function maps null -> Optional.empty().

The underlying reason for this is that Optional cannot contain null. This causes functions that don't follow one of the above points to behave in unexpected ways when it comes to identities4 or composition/chaining.5

Code Smell Complex return types involving Optional, such as using Optional as a type parameter, will likely obfuscate the meaning of your code. Additionally, that return type is not likely to be friendly to or useful for the caller.6

  • A return type of Optional<List<T>> can likely be replaced with just List<T>, returning an empty list when you have no results.
  • A return type of List<Optional<T>> implies that the caller will care about elements that are not present. This is often not the case.

Footnotes

  1. http://blog.joda.org/2015/08/java-se-8-optional-pragmatic-approach.html

  2. https://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type/26328555#26328555

  3. Additionally, the function cannot be composed of any functions that do not handle null in this way.

  4. Optional.flatMap does not satisfy the left-identity monad law for functions that "do stuff" with null.

  5. Optional.map does not satisfy functor composition for functions that "do stuff" with null.

  6. http://mail.openjdk.java.net/pipermail/lambda-libs-spec-experts/2012-September/000014.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment