I've been reading up a lot about the cases where Optional should be used.
A lot of the pages I've read say that Optional shouldn't be used for private instance variables and instead should be returned by getters.
I would have thought that having private instance variables as optional would still be useful. If anybody looks at my code they can see that a value can be empty, instead of having to check the documentation to see if null could be returned.
In Scala null is never used and is only really there for interoperability with Java. It is recommended to always use an optional if a value can be null. This approach makes a lot more sense to me.
Here's a page mentioning it:
https://blog.joda.org/2015/08/java-se-8-optional-pragmatic-approach.html
Here is the example code.
private final String addressLine; // never null
private final String city; // never null
private final String postcode; // optional, thus may be null
// normal getters
public String getAddressLine() { return addressLine; }
public String getCity() { return city; }
// special getter for optional field
public Optional<String> getPostcode() {
return Optional.ofNullable(postcode);
}
The only advantage I can see is that if you want to serialize the object it is now possible as it isn't storing optional in a variable.
The disadvantage is that you don't know postcode could be null until you check the return type of the getter. If you were new to the code you might miss this add extend the class, causing a null pointer exception.
Here is a question asked about Scala's Option.
When to use Option
Why is there a difference between Java and Scala with how optional should be used?
Not all Java developers even agree with the approach you described. Please check this post by the creator of Lombok.
I guess that the reason for a different approach of using Optional in Java is that Java's community lived without it up till Java 8, so most people were used to null. In one hand a lot of new APIs (like findAny from Stream) return Optional, but still a lot of standard library methods just return null, so you always have to remember either to wrap your function calls with Optional.ofNullable or check if the value is not null.
Optional was added to Java 8 but it is discouraged to use it as class fields because Optional is not implementing Serializable (and Java's serialization is used as the default serialization engine by many frameworks or systems like Akka, Spark, Kafka, etc.).
On the other hand Option is very tightly bound with the Scala standard library.
As far as I know, no Scala's standard library APIs return null, but Option, and it is discouraged to use null at all in your Scala code. You can even configure your project that it will fail to compile if null is used.
Option is also Serializable and its normal practice to use is as class fields for values that can be empty.
If you want to use a similar approach in your Java code please check Option from Vavr. It's serializable, so it can be safely used as fields and it also has two subclasses None and Some (similarly as Scala's Option), so it can be used in Vavr's pattern matching:
Match(option).of(
Case($Some($()), "defined"),
Case($None(), "empty")
);
In Scala, Option is tightly integrated into the language's API.
Represents optional values. Instances of Option are either an instance of scala.Some or the object None.
The most idiomatic way to use an scala.Option instance is to treat it as a collection or monad and use map,flatMap, filter, or foreach.
As you can see from the quote above, there is no null explanation there, because it should be used as a monad or as a collection.
In Java, Optional is used to save us from NullPointerException cases, by using it as:
A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
A programming language that shows the user very clearly if the variable can be null or not is Kotlin, by using ? safe call, and shows you compilation errors:
var a: String = "abc"
a = null // compilation error
var b: String? = "abc"
b = null // ok
print(b)
There is the position, that Optional, like Stream, is an iterating «event» class, not deserving to be used as field in a "real" object.
Then there is the short-coming of not being Serializable (which one may work around).
However my opinion is that some variables may be optional, of cardinality 0 and 1.
Just as a list is valid too. With List fields the trend is (IMHO) that it is not let to be null initially, but to always have an (empty) list.
In the same coding style, an Optional ensures that only safe access is used, and especially one may map in a chaining style:
Optional<TextField> t = ...
String s = t.map(t::getText).orElse("N/A");
Optional<String> u = t.map(t::getText);
t.ifPresent(s -> { ... });
Especially the ifPresent ensures not working with null unintendedly.
Optional is a valuable specification.
One reason not to use Optional for instance variables is that it's too easy for the Optional reference itself to be null. This violates an implied contract around Optional, namely that you should never create or encounter a null reference to an Optional.
class Foo {
Optional<Bar> bar;
}
Foo f = new Foo();
if (f.bar.isPresent()) { // NullPointerException
...
}
This is the simplest way to create a class with an Optional field in Java. In a sense the language encourages you to write code like this.
On the other hand, in Scala, the simplest way to define Foo is
case class Foo(bar: Option[Bar])
and it's so easy to do
case class Foo(bar: Option[Bar] = None)
both of which avoid the NPE.
Related
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?
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.
I'm late to the game but for what it's worth, I want to add my 2 Cents. They go against the design goal of Optional, which is well summarized by Stuart Marks's answer, but I'm still convinced of their validity (obviously).
Use Optional Everywhere
In General
I wrote an entire blog post about using Optional but it basically comes down to this:
design your classes to avoid optionality wherever feasibly possible
in all remaining cases, the default should be to use Optional instead of null
possibly make exceptions for:
local variables
return values and arguments to private methods
performance critical code blocks (no guesses, use a profiler)
The first two exceptions can reduce the perceived overhead of wrapping and unwrapping references in Optional. They are chosen such that a null can never legally pass a boundary from one instance into another.
Note that this will almost never allow Optionals in collections which is almost as bad as nulls. Just don't do it. ;)
Regarding your questions
Yes.
If overloading is no option, yes.
If other approaches (subclassing, decorating, ...) are no option, yes.
Please no!
Advantages
Doing this reduces the presence of nulls in your code base, although it does not eradicate them. But that is not even the main point. There are other important advantages:
Clarifies Intent
Using Optional clearly expresses that the variable is, well, optional. Any reader of your code or consumer of your API will be beaten over the head with the fact that there might be nothing there and that a check is necessary before accessing the value.
Removes Uncertainty
Without Optional the meaning of a null occurrence is unclear. It could be a legal representation of a state (see Map.get) or an implementation error like a missing or failed initialization.
This changes dramatically with the persistent use of Optional. Here, already the occurrence of null signifies the presence of a bug. (Because if the value were allowed to be missing, an Optional would have been used.) This makes debugging a null pointer exception much easier as the question of the meaning of this null is already answered.
More Null Checks
Now that nothing can be null anymore, this can be enforced everywhere. Whether with annotations, assertions or plain checks, you never have to think about whether this argument or that return type can be null. It can't!
Disadvantages
Of course, there is no silver bullet...
Performance
Wrapping values (especially primitives) into an extra instance can degrade performance. In tight loops this might become noticeable or even worse.
Note that the compiler might be able to circumvent the extra reference for short lived lifetimes of Optionals. In Java 10 value types might further reduce or remove the penalty.
Serialization
Optional is not serializable but a workaround is not overly complicated.
Invariance
Due to the invariance of generic types in Java, certain operations become cumbersome when the actual value type is pushed into a generic type argument. An example is given here (see "Parametric polymorphism").
Personally, I prefer to use IntelliJ's Code Inspection Tool to use #NotNull and #Nullable checks as these are largely compile time (can have some runtime checks) This has lower overhead in terms of code readability and runtime performance. It is not as rigorous as using Optional, however this lack of rigour should be backed by decent unit tests.
public #Nullable Foo findFoo(#NotNull String id);
public #NotNull Foo doSomething(#NotNull String id, #Nullable Bar barOptional);
public class Book {
private List<Pages> pages;
private #Nullable Index index;
}
List<#Nullable Foo> list = ..
This works with Java 5 and no need to wrap and unwrap values. (or create wrapper objects)
I think the Guava Optional and their wiki page puts it quite well:
Besides the increase in readability that comes from giving null a name, the biggest advantage of Optional is its idiot-proof-ness. It forces you to actively think about the absent case if you want your program to compile at all, since you have to actively unwrap the Optional and address that case. Null makes it disturbingly easy to simply forget things, and though FindBugs helps, we don't think it addresses the issue nearly as well.
This is especially relevant when you're returning values that may or may not be "present." You (and others) are far more likely to forget that other.method(a, b) could return a null value than you're likely to forget that a could be null when you're implementing other.method. Returning Optional makes it impossible for callers to forget that case, since they have to unwrap the object themselves for their code to compile.
-- (Source: Guava Wiki - Using and Avoiding null - What's the point?)
Optional adds some overhead, but I think its clear advantage is to make it explicit
that an object might be absent and it enforces that programmers handle the situation. It prevents that someone forgets the beloved != null check.
Taking the example of 2, I think it is far more explicit code to write:
if(soundcard.isPresent()){
System.out.println(soundcard.get());
}
than
if(soundcard != null){
System.out.println(soundcard);
}
For me, the Optional better captures the fact that there is no soundcard present.
My 2¢ about your points:
public Optional<Foo> findFoo(String id); - I am not sure about this. Maybe I would return a Result<Foo> which might be empty or contain a Foo. It is a similar concept, but not really an Optional.
public Foo doSomething(String id, Optional<Bar> barOptional); - I would prefer #Nullable and a findbugs check, as in Peter Lawrey's answer - see also this discussion.
Your book example - I am not sure if I would use the Optional internally, that might depend on the complexity. For the "API" of a book, I would use an Optional<Index> getIndex() to explicitly indicate that the book might not have an index.
I would not use it in collections, rather not allowing null values in collections
In general, I would try to minimize passing around nulls. (Once burnt...)
I think it is worth to find the appropriate abstractions and indicate to the fellow programmers what a certain return value actually represents.
From Oracle tutorial:
The purpose of Optional is not to replace every single null reference in your codebase but rather to help design better APIs in which—just by reading the signature of a method—users can tell whether to expect an optional value. In addition, Optional forces you to actively unwrap an Optional to deal with the absence of a value; as a result, you protect your code against unintended null pointer exceptions.
In java, just don't use them unless you are addicted to functional programming.
They have no place as method arguments (I promess someone one day will pass you a null optional, not just an optional that is empty).
They make sense for return values but they invite the client class to keep on stretching the behavior-building chain.
FP and chains have little place in an imperative language like java because it makes it very hard to debug, not just to read. When you step to the line, you can't know the state nor intent of the program; you have to step into to figure it out (into code that often isn't yours and many stack frames deep despite step filters) and you have to add lots of breakpoints down to make sure it can stop in the code/lambda you added, instead of simply walking the if/else/call trivial lines.
If you want functional programming, pick something else than java and hope you have the tools for debugging that.
1 - As a public method return type when the method could return null:
Here is a good article that shows usefulness of usecase #1. There this code
...
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
String isocode = country.getIsocode();
isocode = isocode.toUpperCase();
}
}
}
...
is transformed to this
String result = Optional.ofNullable(user)
.flatMap(User::getAddress)
.flatMap(Address::getCountry)
.map(Country::getIsocode)
.orElse("default");
by using Optional as a return value of respective getter methods.
Here is an interesting usage (I believe) for... Tests.
I intend to heavily test one of my projects and I therefore build assertions; only there are things I have to verify and others I don't.
I therefore build things to assert and use an assert to verify them, like this:
public final class NodeDescriptor<V>
{
private final Optional<String> label;
private final List<NodeDescriptor<V>> children;
private NodeDescriptor(final Builder<V> builder)
{
label = Optional.fromNullable(builder.label);
final ImmutableList.Builder<NodeDescriptor<V>> listBuilder
= ImmutableList.builder();
for (final Builder<V> element: builder.children)
listBuilder.add(element.build());
children = listBuilder.build();
}
public static <E> Builder<E> newBuilder()
{
return new Builder<E>();
}
public void verify(#Nonnull final Node<V> node)
{
final NodeAssert<V> nodeAssert = new NodeAssert<V>(node);
nodeAssert.hasLabel(label);
}
public static final class Builder<V>
{
private String label;
private final List<Builder<V>> children = Lists.newArrayList();
private Builder()
{
}
public Builder<V> withLabel(#Nonnull final String label)
{
this.label = Preconditions.checkNotNull(label);
return this;
}
public Builder<V> withChildNode(#Nonnull final Builder<V> child)
{
Preconditions.checkNotNull(child);
children.add(child);
return this;
}
public NodeDescriptor<V> build()
{
return new NodeDescriptor<V>(this);
}
}
}
In the NodeAssert class, I do this:
public final class NodeAssert<V>
extends AbstractAssert<NodeAssert<V>, Node<V>>
{
NodeAssert(final Node<V> actual)
{
super(Preconditions.checkNotNull(actual), NodeAssert.class);
}
private NodeAssert<V> hasLabel(final String label)
{
final String thisLabel = actual.getLabel();
assertThat(thisLabel).overridingErrorMessage(
"node's label is null! I didn't expect it to be"
).isNotNull();
assertThat(thisLabel).overridingErrorMessage(
"node's label is not what was expected!\n"
+ "Expected: '%s'\nActual : '%s'\n", label, thisLabel
).isEqualTo(label);
return this;
}
NodeAssert<V> hasLabel(#Nonnull final Optional<String> label)
{
return label.isPresent() ? hasLabel(label.get()) : this;
}
}
Which means the assert really only triggers if I want to check the label!
Optional class lets you avoid to use null and provide a better alternative:
This encourages the developer to make checks for presence in order to avoid uncaught NullPointerException's.
API becomes better documented because it's possible to see, where to expect the values which can be absent.
Optional provides convenient API for further work with the object:
isPresent(); get(); orElse(); orElseGet(); orElseThrow(); map(); filter(); flatmap().
In addition, many frameworks actively use this data type and return it from their API.
An Optional has similar semantics to an unmodifiable instance of the Iterator design pattern:
it might or might not refer to an object (as given by isPresent())
it can be dereferenced (using get()) if it does refer to an object
but it can not be advanced to the next position in the sequence (it has no next() method).
Therefore consider returning or passing an Optional in contexts where you might previously have considered using a Java Iterator.
Here are some of the methods that you can perform on an instance of Optional<T>:
map
flatMap
orElse
orElseThrow
ifPresentOrElse
get
Here are all the methods that you can perform on null:
(there are none)
This is really an apples to oranges comparison: Optional<T> is an actual instance of an object (unless it is null… but that would probably be a bug) while null is an aborted object. All you can do with null is check whether it is in fact null, or not. So if you like to use methods on objects, Optional<T> is for you; if you like to branch on special literals, null is for you.
null does not compose. You simply can’t compose a value which you can only branch on. But Optional<T> does compose.
You can, for instance, make arbitrary long chains of “apply this function if non-empty” by using map. Or you can effectively make an imperative block of code which consumes the optional if it is non-empty by using ifPresent. Or you can make an “if/else” by using ifPresentOrElse, which consumes the non-empty optional if it is non-empty or else executes some other code.
…And it is at this point that we run into the true limitations of the language in my opinion: for very imperative code you have to wrap them in lambdas and pass them to methods:
opt.ifPresentOrElse(
string -> { // if present...
// ...
}, () -> { // or else...
// ...
}
);
That might not be good enough for some people, style-wise.
It would be more seamless if Optional<T> was an algebraic data type that we could pattern match on (this is obviously pseudo-code:
match (opt) {
Present(str) => {
// ...
}
Empty =>{
// ...
}
}
But anyway, in summary: Optional<T> is a pretty robust empty-or-present object. null is just a sentinel value.
Subjectively disregarded reasons
There seems to be a few people who effectively argue that efficiency should determine whether one should use Optional<T> or branch on the null sentinel value. That seems a bit like making hard and fast rules on when to make objects rather than primitives in the general case. I think it’s a bit ridiculous to use that as the starting point for this discussion when you’re already working in a language where it’s idiomatic to make objects left-and-right, top to bottom, all the time (in my opinion).
I do not think that Optional is a general substitute for methods that potentially return null values.
The basic idea is: The absence of a value does not mean that it potentially is available in the future. It's a difference between findById(-1) and findById(67).
The main information of Optionals for the caller is that he may not count on the value given but it may be available at some time. Maybe it will disappear again and comes back later one more time. It's like an on/off switch. You have the "option" to switch the light on or off. But you have no option if you do not have a light to switch on.
So I find it too messy to introduce Optionals everywhere where previously null was potentially returned. I will still use null, but only in restricted areas like the root of a tree, lazy initialization and explicit find-methods.
Seems Optional is only useful if the type T in Optional is a primitive type like int, long, char, etc. For "real" classes, it does not make sense to me as you can use a null value anyway.
I think it was taken from here (or from another similar language concept).
Nullable<T>
In C# this Nullable<T> was introduced long ago to wrap value types.
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.
Why null object design pattern is better than null object check.
If we look at the memory footprint in null object design pattern we create a new dummy object of same type. Which show if we have object of big size and large number of nullable objects in search query, this pattern will create that much number of null object which will occupy more memory than a simple check which for null which my cost ignoreable delay in performance.
Null Object design pattern
The whole problem with null is that if you try to access a null value the application will throw a NullPointerException and abort.
To reduce the number of class NullXXX in this null object design pattern (its actually just the factory design dattern, not a pattern itself) you could make a static final NullCustomer which is always returned.
In Java 8 you can use the Optional approach in order to tell when a function does not always return values. This approach does not force you to create arbitrary null classes which pollute the overall structure (consider may have to refactor those null classes, too).
Eclipse and IntelliJ also offer compile time annotations #Nullable, #NonNull which give compiler warnings when accessing potential null objects. However, many frameworks are not annotated. IntelliJ therefore tries to discover those potential null accesses with static analysis.
Beside low adoption of this approach IntelliJ and Eclipse use their own annotations (org.eclipse.jdt.annotation.NonNull, com.intellij.annotations.NotNull) that those are not compatible. But, you can store the annotations outside of the code which works in IntelliJ. Eclipse want to implement this in the future, too. The problem is that there are many frameworks providing this feature giving you many different annotations doing the very same. There was JSR-305 which is dormant. It'd provide an annotation in javax. I don't know the reason why they did not pushed this further.
The major advantage of using Null Object rather than null is that using null you have to repeat checks of whether that object is indeed null, particularly in all methods that require that object.
In Java 8, one will have to do:
Object o = Objects.requireNotNull(o); //Throws NullPointerException if o is indeed null.
So, if you have a method that constantly pass the same object into various method, each method will need to check that the object received is not null before using it.
So, a better approach is to have a Null Object, or Optional (Java 8 and higher) so that you don't need to do the null check all the time. Instead one would:
Object o = optional.get(); //Throws NullPointerException if internal value is indeed null.
//Keep using o.
No (really) need for null checking. The fact that you have an Optional means that you might have a value or none.
Null Objects have no side effects because it usually does nothing (usually all methods is an empty method) so there is no need to worry about performance (bottlenecks/optimization/etc).
The main difference (and probably the advantage) of this pattern is distinctness. Think about the following method definition:
public static int length(String str);
This method calculates length of given string. But could argument be null? What will the method do? Throw exception? Return 0? Return -1? We do not know.
Some partial solution can be achieved by writing good java doc. The next and a little bit better solution is using annotations JSR305 annotattion #Nullable or #NotNullable that however can be ignored by developer.
If however you are using Null object pattern (e.g. Optional of guava or java 8) your code looks like the following:
public static int length(Optional<String> str);
So developer must care about wrapping his string into Optional and therefore understands that argument can be null. Attempt to get value from Optional that contains null causes exception that does not always happen when working with regular null.
Obviously you are right that using this pattern causes some additional CPU and memory consumption that however are not significant in most cases.
Suppose you have something like this:
private SomeClass someField;
void someMethod() {
// some other code
someField.method1();
// some other code
someField.method2();
// some other code
someField.method3();
}
Now suppose that there are valid use cases when someField can be null and you don't want to invoke its methods, but you want to execute the other some other code sections of the method. You would need to implement the method as:
void someMethod() {
// do something
if (someField != null) {
someField.method1();
}
// do something
if (someField != null) {
someField.method2();
}
// do something
if (someField != null) {
someField.method3();
}
}
By using Null object with empty (no-op) methods we avoid boilerplate null checks (and the possibility to forget to add the checks for all of the occurrences).
I often find this useful in situations when something is initialized asynchronously or optionally.
I've recently read about this and seen people using this class, but in pretty much all cases, using null would've worked as well - if not more intuitively. Can someone provide a concrete example where Optional would achieve something that null couldn't or in a much cleaner way? The only thing I can think of is to use it with Maps that don't accept null keys, but even that could be done with a side "mapping" of null's value. Can anyone provide me with a more convincing argument?
Guava team member here.
Probably the single biggest disadvantage of null is that it's not obvious what it should mean in any given context: it doesn't have an illustrative name. It's not always obvious that null means "no value for this parameter" -- heck, as a return value, sometimes it means "error", or even "success" (!!), or simply "the correct answer is nothing". Optional is frequently the concept you actually mean when you make a variable nullable, but not always. When it isn't, we recommend that you write your own class, similar to Optional but with a different naming scheme, to make clear what you actually mean.
But I would say the biggest advantage of Optional isn't in readability: the advantage is its idiot-proof-ness. It forces you to actively think about the absent case if you want your program to compile at all, since you have to actively unwrap the Optional and address that case. Null makes it disturbingly easy to simply forget things, and though FindBugs helps, I don't think it addresses the issue nearly as well. This is especially relevant when you're returning values that may or may not be "present." You (and others) are far more likely to forget that other.method(a, b) could return a null value than you're likely to forget that a could be null when you're implementing other.method. Returning Optional makes it impossible for callers to forget that case, since they have to unwrap the object themselves.
For these reasons, we recommend that you use Optional as a return type for your methods, but not necessarily in your method arguments.
(This is totally cribbed, by the way, from the discussion here.)
It really looks like the Maybe Monad pattern from Haskell.
You should read the following, Wikipedia Monad (functional programming):
And read From Optional to Monad with Guava on Kerflyn's Blog, which discusses about the Optional of Guava used as a Monad:
Edit:
With Java8, there's a built-in Optional that has monadic operators like flatMap. This has been a controversial subject but finally has been implemented.
See http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html
public Optional<String> tryFindSimilar(String s) //...
Optional<Optional<String>> bad = opt.map(this::tryFindSimilar);
Optional<String> similar = opt.flatMap(this::tryFindSimilar);
The flatMap operator is essential to allow monadic operations, and permits to easily chain calls that all return Optional results.
Think about it, if you used the map operator 5 times you would end up with an Optional<Optional<Optional<Optional<Optional<String>>>>>, while using flatMap would give you Optional<String>
Since Java8 I would rather not use Guava's Optional which is less powerful.
One good reason to use it is that it makes your nulls very meaningful. Instead of returning a null that could mean many things (like error, or failure, or empty,etc) you can put a 'name' to your null. Look at this example:
lets define a basic POJO:
class PersonDetails {
String person;
String comments;
public PersonDetails(String person, String comments) {
this.person = person;
this.comments = comments;
}
public String getPerson() {
return person;
}
public String getComments() {
return comments;
}
}
Now lets make use of this simple POJO:
public Optional<PersonDetails> getPersonDetailstWithOptional () {
PersonDetails details = null; /*details of the person are empty but to the caller this is meaningless,
lets make the return value more meaningful*/
if (details == null) {
//return an absent here, caller can check for absent to signify details are not present
return Optional.absent();
} else {
//else return the details wrapped in a guava 'optional'
return Optional.of(details);
}
}
Now lets avoid using null and do our checks with Optional so its meaningful
public void checkUsingOptional () {
Optional<PersonDetails> details = getPersonDetailstWithOptional();
/*below condition checks if persons details are present (notice we dont check if person details are null,
we use something more meaningful. Guava optional forces this with the implementation)*/
if (details.isPresent()) {
PersonDetails details = details.get();
// proceed with further processing
logger.info(details);
} else {
// do nothing
logger.info("object was null");
}
assertFalse(details.isPresent());
}
thus in the end its a way to make nulls meaningful, & less ambiguity.
The most important advantage of Optional is that it adds more details to the contract between the implementer and caller of a function. For this reason is both useful for parameters and return type.
If you make the convention to always have Optional for possible null objects you add more clarifications to cases like:
Optional<Integer> maxPrime(Optional<Integer> from, Optional<Integer> to)
The contract here clearly specifies that there is a chance that a result is not returned but also shows that it will work with from and to as absent.
Optional<Integer> maxPrime(Optional<Integer> from, Integer to)
The contract specifies that the from is optional so an absent value might have a special meaning like start from 2. I can expect that a null value for the to parameter will throw an exception.
So the good part of using Optional is that the contract became both descriptive (similar with #NotNull annotation) but also formal since you must write code .get() to cope with Optional.
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?
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.
I'm late to the game but for what it's worth, I want to add my 2 Cents. They go against the design goal of Optional, which is well summarized by Stuart Marks's answer, but I'm still convinced of their validity (obviously).
Use Optional Everywhere
In General
I wrote an entire blog post about using Optional but it basically comes down to this:
design your classes to avoid optionality wherever feasibly possible
in all remaining cases, the default should be to use Optional instead of null
possibly make exceptions for:
local variables
return values and arguments to private methods
performance critical code blocks (no guesses, use a profiler)
The first two exceptions can reduce the perceived overhead of wrapping and unwrapping references in Optional. They are chosen such that a null can never legally pass a boundary from one instance into another.
Note that this will almost never allow Optionals in collections which is almost as bad as nulls. Just don't do it. ;)
Regarding your questions
Yes.
If overloading is no option, yes.
If other approaches (subclassing, decorating, ...) are no option, yes.
Please no!
Advantages
Doing this reduces the presence of nulls in your code base, although it does not eradicate them. But that is not even the main point. There are other important advantages:
Clarifies Intent
Using Optional clearly expresses that the variable is, well, optional. Any reader of your code or consumer of your API will be beaten over the head with the fact that there might be nothing there and that a check is necessary before accessing the value.
Removes Uncertainty
Without Optional the meaning of a null occurrence is unclear. It could be a legal representation of a state (see Map.get) or an implementation error like a missing or failed initialization.
This changes dramatically with the persistent use of Optional. Here, already the occurrence of null signifies the presence of a bug. (Because if the value were allowed to be missing, an Optional would have been used.) This makes debugging a null pointer exception much easier as the question of the meaning of this null is already answered.
More Null Checks
Now that nothing can be null anymore, this can be enforced everywhere. Whether with annotations, assertions or plain checks, you never have to think about whether this argument or that return type can be null. It can't!
Disadvantages
Of course, there is no silver bullet...
Performance
Wrapping values (especially primitives) into an extra instance can degrade performance. In tight loops this might become noticeable or even worse.
Note that the compiler might be able to circumvent the extra reference for short lived lifetimes of Optionals. In Java 10 value types might further reduce or remove the penalty.
Serialization
Optional is not serializable but a workaround is not overly complicated.
Invariance
Due to the invariance of generic types in Java, certain operations become cumbersome when the actual value type is pushed into a generic type argument. An example is given here (see "Parametric polymorphism").
Personally, I prefer to use IntelliJ's Code Inspection Tool to use #NotNull and #Nullable checks as these are largely compile time (can have some runtime checks) This has lower overhead in terms of code readability and runtime performance. It is not as rigorous as using Optional, however this lack of rigour should be backed by decent unit tests.
public #Nullable Foo findFoo(#NotNull String id);
public #NotNull Foo doSomething(#NotNull String id, #Nullable Bar barOptional);
public class Book {
private List<Pages> pages;
private #Nullable Index index;
}
List<#Nullable Foo> list = ..
This works with Java 5 and no need to wrap and unwrap values. (or create wrapper objects)
I think the Guava Optional and their wiki page puts it quite well:
Besides the increase in readability that comes from giving null a name, the biggest advantage of Optional is its idiot-proof-ness. It forces you to actively think about the absent case if you want your program to compile at all, since you have to actively unwrap the Optional and address that case. Null makes it disturbingly easy to simply forget things, and though FindBugs helps, we don't think it addresses the issue nearly as well.
This is especially relevant when you're returning values that may or may not be "present." You (and others) are far more likely to forget that other.method(a, b) could return a null value than you're likely to forget that a could be null when you're implementing other.method. Returning Optional makes it impossible for callers to forget that case, since they have to unwrap the object themselves for their code to compile.
-- (Source: Guava Wiki - Using and Avoiding null - What's the point?)
Optional adds some overhead, but I think its clear advantage is to make it explicit
that an object might be absent and it enforces that programmers handle the situation. It prevents that someone forgets the beloved != null check.
Taking the example of 2, I think it is far more explicit code to write:
if(soundcard.isPresent()){
System.out.println(soundcard.get());
}
than
if(soundcard != null){
System.out.println(soundcard);
}
For me, the Optional better captures the fact that there is no soundcard present.
My 2¢ about your points:
public Optional<Foo> findFoo(String id); - I am not sure about this. Maybe I would return a Result<Foo> which might be empty or contain a Foo. It is a similar concept, but not really an Optional.
public Foo doSomething(String id, Optional<Bar> barOptional); - I would prefer #Nullable and a findbugs check, as in Peter Lawrey's answer - see also this discussion.
Your book example - I am not sure if I would use the Optional internally, that might depend on the complexity. For the "API" of a book, I would use an Optional<Index> getIndex() to explicitly indicate that the book might not have an index.
I would not use it in collections, rather not allowing null values in collections
In general, I would try to minimize passing around nulls. (Once burnt...)
I think it is worth to find the appropriate abstractions and indicate to the fellow programmers what a certain return value actually represents.
From Oracle tutorial:
The purpose of Optional is not to replace every single null reference in your codebase but rather to help design better APIs in which—just by reading the signature of a method—users can tell whether to expect an optional value. In addition, Optional forces you to actively unwrap an Optional to deal with the absence of a value; as a result, you protect your code against unintended null pointer exceptions.
In java, just don't use them unless you are addicted to functional programming.
They have no place as method arguments (I promess someone one day will pass you a null optional, not just an optional that is empty).
They make sense for return values but they invite the client class to keep on stretching the behavior-building chain.
FP and chains have little place in an imperative language like java because it makes it very hard to debug, not just to read. When you step to the line, you can't know the state nor intent of the program; you have to step into to figure it out (into code that often isn't yours and many stack frames deep despite step filters) and you have to add lots of breakpoints down to make sure it can stop in the code/lambda you added, instead of simply walking the if/else/call trivial lines.
If you want functional programming, pick something else than java and hope you have the tools for debugging that.
1 - As a public method return type when the method could return null:
Here is a good article that shows usefulness of usecase #1. There this code
...
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
String isocode = country.getIsocode();
isocode = isocode.toUpperCase();
}
}
}
...
is transformed to this
String result = Optional.ofNullable(user)
.flatMap(User::getAddress)
.flatMap(Address::getCountry)
.map(Country::getIsocode)
.orElse("default");
by using Optional as a return value of respective getter methods.
Here is an interesting usage (I believe) for... Tests.
I intend to heavily test one of my projects and I therefore build assertions; only there are things I have to verify and others I don't.
I therefore build things to assert and use an assert to verify them, like this:
public final class NodeDescriptor<V>
{
private final Optional<String> label;
private final List<NodeDescriptor<V>> children;
private NodeDescriptor(final Builder<V> builder)
{
label = Optional.fromNullable(builder.label);
final ImmutableList.Builder<NodeDescriptor<V>> listBuilder
= ImmutableList.builder();
for (final Builder<V> element: builder.children)
listBuilder.add(element.build());
children = listBuilder.build();
}
public static <E> Builder<E> newBuilder()
{
return new Builder<E>();
}
public void verify(#Nonnull final Node<V> node)
{
final NodeAssert<V> nodeAssert = new NodeAssert<V>(node);
nodeAssert.hasLabel(label);
}
public static final class Builder<V>
{
private String label;
private final List<Builder<V>> children = Lists.newArrayList();
private Builder()
{
}
public Builder<V> withLabel(#Nonnull final String label)
{
this.label = Preconditions.checkNotNull(label);
return this;
}
public Builder<V> withChildNode(#Nonnull final Builder<V> child)
{
Preconditions.checkNotNull(child);
children.add(child);
return this;
}
public NodeDescriptor<V> build()
{
return new NodeDescriptor<V>(this);
}
}
}
In the NodeAssert class, I do this:
public final class NodeAssert<V>
extends AbstractAssert<NodeAssert<V>, Node<V>>
{
NodeAssert(final Node<V> actual)
{
super(Preconditions.checkNotNull(actual), NodeAssert.class);
}
private NodeAssert<V> hasLabel(final String label)
{
final String thisLabel = actual.getLabel();
assertThat(thisLabel).overridingErrorMessage(
"node's label is null! I didn't expect it to be"
).isNotNull();
assertThat(thisLabel).overridingErrorMessage(
"node's label is not what was expected!\n"
+ "Expected: '%s'\nActual : '%s'\n", label, thisLabel
).isEqualTo(label);
return this;
}
NodeAssert<V> hasLabel(#Nonnull final Optional<String> label)
{
return label.isPresent() ? hasLabel(label.get()) : this;
}
}
Which means the assert really only triggers if I want to check the label!
Optional class lets you avoid to use null and provide a better alternative:
This encourages the developer to make checks for presence in order to avoid uncaught NullPointerException's.
API becomes better documented because it's possible to see, where to expect the values which can be absent.
Optional provides convenient API for further work with the object:
isPresent(); get(); orElse(); orElseGet(); orElseThrow(); map(); filter(); flatmap().
In addition, many frameworks actively use this data type and return it from their API.
An Optional has similar semantics to an unmodifiable instance of the Iterator design pattern:
it might or might not refer to an object (as given by isPresent())
it can be dereferenced (using get()) if it does refer to an object
but it can not be advanced to the next position in the sequence (it has no next() method).
Therefore consider returning or passing an Optional in contexts where you might previously have considered using a Java Iterator.
Here are some of the methods that you can perform on an instance of Optional<T>:
map
flatMap
orElse
orElseThrow
ifPresentOrElse
get
Here are all the methods that you can perform on null:
(there are none)
This is really an apples to oranges comparison: Optional<T> is an actual instance of an object (unless it is null… but that would probably be a bug) while null is an aborted object. All you can do with null is check whether it is in fact null, or not. So if you like to use methods on objects, Optional<T> is for you; if you like to branch on special literals, null is for you.
null does not compose. You simply can’t compose a value which you can only branch on. But Optional<T> does compose.
You can, for instance, make arbitrary long chains of “apply this function if non-empty” by using map. Or you can effectively make an imperative block of code which consumes the optional if it is non-empty by using ifPresent. Or you can make an “if/else” by using ifPresentOrElse, which consumes the non-empty optional if it is non-empty or else executes some other code.
…And it is at this point that we run into the true limitations of the language in my opinion: for very imperative code you have to wrap them in lambdas and pass them to methods:
opt.ifPresentOrElse(
string -> { // if present...
// ...
}, () -> { // or else...
// ...
}
);
That might not be good enough for some people, style-wise.
It would be more seamless if Optional<T> was an algebraic data type that we could pattern match on (this is obviously pseudo-code:
match (opt) {
Present(str) => {
// ...
}
Empty =>{
// ...
}
}
But anyway, in summary: Optional<T> is a pretty robust empty-or-present object. null is just a sentinel value.
Subjectively disregarded reasons
There seems to be a few people who effectively argue that efficiency should determine whether one should use Optional<T> or branch on the null sentinel value. That seems a bit like making hard and fast rules on when to make objects rather than primitives in the general case. I think it’s a bit ridiculous to use that as the starting point for this discussion when you’re already working in a language where it’s idiomatic to make objects left-and-right, top to bottom, all the time (in my opinion).
I do not think that Optional is a general substitute for methods that potentially return null values.
The basic idea is: The absence of a value does not mean that it potentially is available in the future. It's a difference between findById(-1) and findById(67).
The main information of Optionals for the caller is that he may not count on the value given but it may be available at some time. Maybe it will disappear again and comes back later one more time. It's like an on/off switch. You have the "option" to switch the light on or off. But you have no option if you do not have a light to switch on.
So I find it too messy to introduce Optionals everywhere where previously null was potentially returned. I will still use null, but only in restricted areas like the root of a tree, lazy initialization and explicit find-methods.
Seems Optional is only useful if the type T in Optional is a primitive type like int, long, char, etc. For "real" classes, it does not make sense to me as you can use a null value anyway.
I think it was taken from here (or from another similar language concept).
Nullable<T>
In C# this Nullable<T> was introduced long ago to wrap value types.
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.
I am wondering if there is a ready made Java class that can be used similarly with Guava's Optional but treats null and absent differently.
I have use case that requires to pass a method parameter with String value, null value or absent (does not provide anything). Null is a purely valid value and carries special meaning.
I tried to use Guava's Optional but found that it cannot differentiate null and absent. Passwing null to Optional means absent.
I am wondering if there is a ready made Java utility that can be used for my usecase: It can carry a value, null value or no value (absent).
many thanks
The java language can do it: Use a token object to represent "absent".
Say it's a String type:
private static final String ABSENT = new String(""); // not interned
private String attribute = ABSENT;
public boolean attributeIsSet() {
return attribute == ABSENT; // identity comparison
}
public String getAttribute() {
if (attributeIsSet())
return attribute;
throw new IllegalStateException(); // or whatever
}
This allows null to be a valid value.
You should use Optional.
Optional is you know that something is either present or not. Add the meaning null to Optional by returning... null.
Optional<A> a = Optional.of(new A()); // We know that A is present.
Optional<B> b = Optional.absent(); // We know that B is absent.
Optional<C> c = null; // We don't know if C is present or absent.
Working with null isn't bad: it's error-prone. So be careful, document properly what you want to do and how null should be interpreted.
Null ... carries special meaning.
Whenever you find yourself saying this, it should be a red flag that your design merits re-thinking, as null by definition carries no meaning. Lets step back and look at your requirements (feel free to update the question with better descriptions of your intent if this is inaccurate):
Absence: Indicates we've nothing to do here at all
null: Indicates a "special value", such as DEFAULT or FALLBACK, which should be handled specially
Value: A "normal" value, including the empty string, that can be handled directly
This is not an unusual problem, (particularly when working with nullable database columns, as I think you are) and Optional can quite successfully represent this, but we need to structure it better.
While we can't avoid NULLs in databases, we can strive to restrict their scope to the minimal code surrounding our database access behavior, and expose it no further than that. We conceptually do this by converting nullable fields to Optionals, as you know. So col VARCHAR NULL should always be converted into Java as an Optional<String> col as soon as possible.
But now we need to represent the absence case, such as when we SELECT col FROM table LIMIT 1 and get nothing back from our query. Obviously, this should be handled differently than if we get back a NULL.
We have a couple of choices, but they all boil down to wrapping our Optional<String> in another layer somehow.
In many cases you can simply use a List or other Collection. By passing back a non-null collection we can generally handle the absent case trivially, as our code will simply not enter whatever loop would otherwise process the data if the List is empty. So List<Optional<String>> is one option.
If that's not possible, and you really want to limit the behavior to one-or-none, such as in the LIMIT 1 example above, simply wrap it in another Optional, i.e. Optional<Optional<String>>. This clearly conveys the difference between absence of a result, and absence of a value in a type-safe manner.
A little more work, but even better is to properly represent this structure in its own class (any time you have generics inside generics, consider creating a proper holding class), since really what we're talking about is a optional piece of data, which may itself contain an optional piece of data.
public class Row {
private final Optional<String> col;
public Row(#Nullable String col) {
this.col = Optional.fromNullable(col);
}
public Optional<String> getCol() {
return col;
}
}
Then you pass around Optional<Row> objects, which very clearly either exists or doesn't, and either contain a result, or not. All type-safe, and no nulls needed.
tl;dr: This can be rationally represented with Optional<Optional<String>>, or see above for additional suggestions.
Isn't an empty String ("") the same as 'no value' for a string? Obviously this wouldn't work for numbers, but you're specifically talking about a String.