Java – Uses for Optional

javajava-8optional

Having been using Java 8 now for 6+ months or so, I'm pretty happy with the new API changes. One area I'm still not confident in is when to use Optional. I seem to swing between wanting to use it everywhere something may be null, and nowhere at all.

There seem to be a lot of situations when I could use it, and I'm never sure if it adds benefits (readability / null safety) or just causes additional overhead.

So, I have a few examples, and I'd be interested in the community's thoughts on whether Optional is beneficial.

1 – As a public method return type when the method could return null:

public Optional<Foo> findFoo(String id);

2 – As a method parameter when the param may be null:

public Foo doSomething(String id, Optional<Bar> barOptional);

3 – As an optional member of a bean:

public class Book {

  private List<Pages> pages;
  private Optional<Index> index;

}

4 – In Collections:

In general I don't think:

List<Optional<Foo>>

adds anything – especially since one can use filter() to remove null values etc, but are there any good uses for Optional in collections?

Any cases I've missed?

Best Answer

The main design goal of Optional is to provide a means for a function returning a value to indicate the absence of a return value. See this discussion. This allows the caller to continue a chain of fluent method calls.

This most closely matches use case #1 in the OP's question. Although, absence of a value is a more precise formulation than null since something like IntStream.findFirst could never return null.


For use case #2, passing an optional argument to a method, this could be made to work, but it's rather clumsy. Suppose you have a method that takes a string followed by an optional second string. Accepting an Optional as the second arg would result in code like this:

foo("bar", Optional.of("baz"));
foo("bar", Optional.empty());

Even accepting null is nicer:

foo("bar", "baz");
foo("bar", null);

Probably the best is to have an overloaded method that accepts a single string argument and provides a default for the second:

foo("bar", "baz");
foo("bar");

This does have limitations, but it's much nicer than either of the above.

Use cases #3 and #4, having an Optional in a class field or in a data structure, is considered a misuse of the API. First, it goes against the main design goal of Optional as stated at the top. Second, it doesn't add any value.

There are three ways to deal with the absence of a value in an Optional: to provide a substitute value, to call a function to provide a substitute value, or to throw an exception. If you're storing into a field, you'd do this at initialization or assignment time. If you're adding values into a list, as the OP mentioned, you have the additional choice of simply not adding the value, thereby "flattening" out absent values.

I'm sure somebody could come up with some contrived cases where they really want to store an Optional in a field or a collection, but in general, it is best to avoid doing this.