1 - As a public method return type when the method could return null:
This is the intended use case for Optional, as seen in the JDK API docs:
Optional is primarily intended for use as a method return type where
there is a clear need to represent "no result," and where using null
is likely to cause errors.
Optional represents one of two states:
- it has a value (isPresentreturnstrue)
- it doesn't have a value (isEmptyreturnstrue)
So if you have a method that returns either something or nothing, this is the ideal use case for Optional.
Here's an example:
Optional<Guitarist> findByLastName(String lastName);
This method takes a parameter used to search for an entity in the database. It's possible that no such entity exists, so using an Optional return type is a good idea since it forces whoever is calling the method to consider the empty scenario. This reduces chances of a NullPointerException.
2 - As a method parameter when the param may be null:
Although technically possible, this is not the intended use case of Optional.
Let's consider your proposed method signature:
public Foo doSomething(String id, Optional<Bar> barOptional);
The main problem is that we could call doSomething where barOptional has one of 3 states:
- an Optionalwith a value e.g.doSomething("123", Optional.of(new Bar())
- an empty Optionale.g.doSomething("123", Optional.empty())
- nulle.g.- doSomething("123", null)
These 3 states would need to be handled in the method implementation appropriately.
A better solution is to implement an overloaded method.
public Foo doSomething(String id);
public Foo doSomething(String id, Bar bar);
This makes it very clear to the consumer of the API which method to call, and null does not need to be passed.
3 - As an optional member of a bean:
Given your example Book class:
public class Book {
  private List<Pages> pages;
  private Optional<Index> index;
}
The Optional class variable suffers from the same issue as the Optional method parameter discussed above. It can have one of 3 states: present, empty, or null.
Other possible issues include:
- serialization: if you implement Serializableand try to serialize an object of this class, you will encounter ajava.io.NotSerializableExceptionsinceOptionalwas not designed for this use case
- transforming to JSON: when serializing to JSON an Optionalfield may get mapped in an undesirable way e.g.{"empty":false,"present":true}.
Although if you use the popular Jackson library, it does provide a solution to this problem.
Despite these issues, Oracle themselves published this blog post at the time of the Java 8 Optional release in 2014. It contains code examples using Optional for class variables.
public class Computer {
  private Optional<Soundcard> soundcard;  
  public Optional<Soundcard> getSoundcard() { ... }
  ...
}
In the following years though, developers have found better alternatives such as implementing a getter method to create the Optional object.
public class Book {
    private List<Pages> pages;
    private Index index;
    public Optional<Index> getIndex() {
        return Optional.ofNullable(index);
    }
}
Here we use the ofNullable method to return an Optional with a value if index is non-null, or otherwise an empty Optional.
4 - In Collections:
I agree that creating a List of Optional (e.g. List<Optional<Foo>>) doesn't add anything.
Instead, just don't include the item in the List if it's not present.