\htmlhr
\chapterAndLabel{Optional Checker for possibly-present data}{optional-checker}

Use of the Optional Checker guarantees that your program will not suffer
a \<NoSuchElementException> when calling
methods on an expression of \<Optional> type.
The Optional Checker also enforces Stuart Marks's style guidelines (see below).

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.
Most notably, the Optional Checker guarantees your code will not suffer a
\<NoSuchElementException> due to use of an empty \<Optional>.

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.


\sectionAndLabel{How to run the Optional Checker}{optional-run-checker}

\begin{Verbatim}
javac -processor optional MyFile.java ...
javac -processor org.checkerframework.checker.optional.OptionalChecker 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}{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}

\subsectionAndLabel{Optional method annotations}{optional-method-annotations}

The Optional Checker supports several annotations that specify method
behavior.  These are declaration annotations, not type annotations:  they
apply to the method itself rather than to some particular type.

\begin{description}

\item[\refqualclass{checker/optional/qual}{RequiresPresent}]
  indicates a method precondition:  The annotated method expects the
  specified expressions to be a present Optional when this
  method is invoked. \<@RequiresPresent> is a useful annotation for a method
  that requires a \<@MaybePresent> field to be \<@Present>.
\item[\refqualclass{checker/optional/qual}{EnsuresPresent}]
  indicates a method postcondition.
  The successful return (i.e., a non-exceptional return) of the annotated
  method results in the given Optional expression being present. See the Javadoc
  for examples of its use.
\item[\refqualclass{checker/optional/qual}{EnsuresPresentIf}]
  indicates a method postcondition.  With \<@EnsuresPresent>, the given
  Optional expression is present after the method returns.  With
  \<@EnsuresPresentIf>, if the annotated
  method returns the given boolean value (true or false), then the given
  Optional expression is present. See the Javadoc for examples of their use.

\end{description}


\sectionAndLabel{What the Optional Checker guarantees}{optional-guarantees}

The Optional Checker guarantees that your code will not throw a \<NoSuchElementException> exception
due to use of an absent \<Optional> where a present \<Optional> is needed.
More specifically, the Optional Checker will issue an error if you call
\sunjavadoc{java.base/java/util/Optional.html\#get()}{get}
or
\sunjavadoc{java.base/java/util/Optional.html\#orElseThrow()}{orElseThrow()}
on a \<@MaybePresent Optional> receiver, because each of these methods
throws a \<NoSuchElementException> exception if the receiver is a possibly-absent
\<Optional>.

By contrast, the Optional Checker does not issue an error if you call
\sunjavadoc{java.base/java/util/Optional.html\#orElseThrow(java.util.function.Supplier)}{orElseThrow(Supplier)}
with a possibly-absent \<Optional>.  That method call does not
% necessarily
throw \<NoSuchElementException>.  The Optional Checker assumes that the
programmer has mechanisms in place to handle whatever exception it throws.
If you wish for the Optional Checker to warn about calling
\<orElseThrow(Supplier)> on a possibly-absent \<Optional>, then you can use
a stub file (\sectionpageref{stub}) to annotate its receiver as \<@Present>.

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}).

\sectionAndLabel{Suppressing optional warnings}{suppressing-warnings-optional}

It is often best to change the code or annotations when the Optional Checker
reports a warning.
Alternatively, you might choose to suppress the warning.
This does not change the code but prevents the warning from being presented to
you.

\begin{sloppypar}
The Checker Framework supplies several ways to suppress warnings.
The \<@SuppressWarnings("optional")> annotation is specific to warnings raised
by the Optional Checker.
See Chapter~\ref{suppressing-warnings} for additional usages.
An example use is
\end{sloppypar}

%BEGIN LATEX
\begin{smaller}
%END LATEX
\begin{Verbatim}
    // might return a possibly-empty Optional
    Optional<T> wrapWithOptional(...) { ... }

    void myMethod() {
      @SuppressWarnings("optional") // with argument x, wrapWithOptional always returns a present Optional
      @Present Optional<T> optX = wrapWithOptional(x);
    }
\end{Verbatim}
%BEGIN LATEX
\end{smaller}
%END LATEX

The Optional Checker also permits the use of method calls and assertions to
suppress warnings; see immediately below.


\subsectionAndLabel{Suppressing warnings with assertions and method calls}{suppressing-optional-warnings-with-assertions-and-method-calls}

Occasionally, it is inconvenient or
verbose to use the \<@SuppressWarnings> annotation.  For example, Java does
not permit annotations such as \<@SuppressWarnings> to appear on
statements, expressions, static initializers, etc.
Here are three ways to suppress a warning in such cases:
\begin{itemize}
\item
  Create a local variable to hold a subexpression, and
  suppress a warning on the local variable declaration.
\item
  Use the \<@AssumeAssertion> string in
  an \<assert> message (see Section~\ref{assumeassertion}).
\item
  Write a call to the
  \refmethod{checker/optional/util}{OptionalUtil}{castPresent}{(java.util.Optional)} method.
\end{itemize}

The rest of this section discusses the \<castPresent> method.
It is useful if you wish to suppress a warning within an expression.

The Optional Checker considers both the return value, and also the
argument, to be an instance of a present Optional after the \<castPresent>
method call.
The Optional Checker issues no warnings in any of the following
code:

\begin{Verbatim}
  // One way to use castPresent as a cast:
  @Present Optional<String> optString = castPresent(possiblyEmpty1);

  // Another way to use castPresent as a cast:
  castPresent(possiblyEmpty2).toString();

  // It is possible, but not recommmended, to use castPresent as a statement:
  // (It would be better to write an assert statement with @AssumeAssertion
  // in its message, instead.)
  castPresent(possiblyEmpty3);
  possiblyEmpty3.toString();
\end{Verbatim}

  The \<castPresent> method throws \<AssertionError> if Java assertions are
  enabled and the argument is an empty \<Optional>.
  However, it is not intended for general defensive programming; see
  Section~\ref{defensive-programming}.

  To use the \<castPresent> method, the \<checker-util.jar> file
  must be on the classpath at run time.

%  LocalWords:  isPresent NoSuchElementException MaybePresent PolyPresent
%%  LocalWords:  orElseThrow nullable RequiresPresent EnsuresPresent util
% LocalWords:  EnsuresPresentIf AssumeAssertion OptionalUtil castPresent
% LocalWords:  AssertionError
