blob: c57366408f54e7a5862c324633e6d7656c3989ac [file] [log] [blame] [edit]
\htmlhr
\chapterAndLabel{Optional Checker for possibly-present data}{optional-checker}
Java 8 introduced the \sunjavadoc{java.base/java/util/Optional.html}{Optional}
class, a container that is either empty or contains a non-null value.
Using \<Optional> is intended to help programmers remember to check whether
data is present or not. However, \<Optional> itself is prone to misuse.
The article
\href{https://homes.cs.washington.edu/~mernst/advice/nothing-is-better-than-optional.html}{Nothing
is better than the \<Optional> type} gives reasons to use
regular nullable references rather than \<Optional>. However, if you do use
\<Optional>, then the Optional Checker will help you avoid
\<Optional>'s pitfalls.
Stuart Marks gave
\href{https://stuartmarks.wordpress.com/2016/09/27/vjug24-session-on-optional/}{7
rules} to avoid problems with Optional:
\begin{enumerate}
\item
Never, ever, use \<null> for an \<Optional> variable or return value.
\item
Never use \sunjavadoc{java.base/java/util/Optional.html\#get()}{Optional.get()} unless you can prove that the Optional is present.
\item
Prefer alternative APIs over
\sunjavadoc{java.base/java/util/Optional.html\#isPresent()}{Optional.isPresent()}
and \sunjavadoc{java.base/java/util/Optional.html\#get()}{Optional.get()}.
\item
It's generally a bad idea to create an \<Optional> for the specific
purpose of chaining methods from it to get a value.
\item
If an Optional chain has a nested \<Optional> chain, or has an
intermediate result of \<Optional>, it's probably too complex.
\item
Avoid using \<Optional> in fields, method parameters, and collections.
\item
Don't use an \<Optional> to wrap any collection type (\<List>, \<Set>,
\<Map>). Instead, use an empty collection to represent the absence of
values.
\end{enumerate}
Rule \#1 is guaranteed by the Nullness Checker
(\chapterpageref{nullness-checker}).
Rules \#2--\#7 are guaranteed by the Optional Checker, described in this chapter.
(Exception: Rule \#5 is not yet implemented and will be checked by the
Optional Checker in the future.)
% They are all AST checks that would be easy to add later.
Use of the Optional Checker guarantees that your program will not suffer a
\<NullPointerException> nor a \<NoSuchElementException> when calling
methods on an expression of \<Optional> type.
\sectionAndLabel{How to run the Optional Checker}{optional-run-checker}
\begin{Verbatim}
javac -processor optional MyFile.java ...
\end{Verbatim}
\sectionAndLabel{Optional annotations}{optional-annotations}
These qualifiers make up the Optional type system:
\begin{description}
% alternate name: PossiblyAbsent. But, the Optional Javadoc is careful
% never to use the term "absent", and it's nice parallelism to have
% "Present" in the names of all the annotations.
\item[\refqualclass{checker/optional/qual}{MaybePresent}]
The annotated \<Optional> container may or may not contain a value.
This is the default type, so programmers do not have to write it.
\item[\refqualclass{checker/optional/qual}{Present}]
The annotated \<Optional> container definitely contains a (non-null) value.
\item[\refqualclass{checker/optional/qual}{OptionalBottom}]
The annotated expression evaluates to \<null> rather than to an \<Optional> container.
Programmers rarely write this annotation.
\item[\refqualclass{checker/optional/qual}{PolyPresent}]
indicates qualifier polymorphism.
For a description of qualifier polymorphism, see
Section~\ref{method-qualifier-polymorphism}.
\end{description}
The subtyping hierarchy of the Optional Checker's qualifiers is shown in
Figure~\ref{fig-optional-hierarchy}.
\begin{figure}
\includeimage{optional-subtyping}{3.5cm}
\caption{The subtyping relationship of the Optional Checker's qualifiers.}
\label{fig-optional-hierarchy}
\end{figure}
\sectionAndLabel{What the Optional Checker guarantees}{optional-guarantees}
The Optional Checker guarantees that your code will not throw an exception
due to use of an absent \<Optional> where a present \<Optional> is needed.
More specifically, the Optional Checker will issue a warning if you call
\sunjavadoc{java.base/java/util/Optional.html\#get()
}{get}
or
\sunjavadoc{java.base/java/util/Optional.html\#orElseThrow(java.util.function.Supplier)}{orElseThrow}
on a \<@MaybePresent Optional> receiver, because each of these methods
throws an exception if the receiver is an absent
\<Optional>.
The Optional Checker does not check nullness properties, such as requiring
that the argument to
\sunjavadoc{java.base/java/util/Optional.html\#of(T)}{of}
is non-null or guaranteeing that the result of
\sunjavadoc{java.base/java/util/Optional.html\#get()}{get}
is non-null. To obtain such a guarantee, run both the Optional Checker and
the Nullness Checker (\chapterpageref{nullness-checker}).
As with any checker, the guarantee is subject to certain limitations (see
Section~\ref{checker-guarantees}).
% LocalWords: isPresent NoSuchElementException MaybePresent PolyPresent
%% LocalWords: orElseThrow nullable