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 (
isPresent
returns true
)
- it doesn't have a value (
isEmpty
returns true
)
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
Optional
with a value e.g. doSomething("123", Optional.of(new Bar())
- an empty
Optional
e.g. doSomething("123", Optional.empty())
null
e.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
Serializable
and try to serialize an object of this class, you will encounter a java.io.NotSerializableException
since Optional
was not designed for this use case
- transforming to JSON: when serializing to JSON an
Optional
field 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.
Map<Character, String>
. If there is no substitution I can use this:Optional.ofNullable(map.get(c)).orElse(String.valueOf(c))
. Also note that Optional was stolen from Guava and it has a much nicer syntax:Optional.fromNullable(map.get(c)).or(String.valueOf(c));
– Rhnegative.filter(Optional::absent)
"null values" out – RhnegativegetOrDefault()
? – Alysiaalyson