Do you know how to use Optional? Find out in the latest by Simon and Mikalai.
August 11, 2020 | Download a PDF of this article
More quiz questions available here
If you have worked on our quiz questions in the past, you know none of them is easy. They model the difficult questions from certification examinations. The “intermediate” and “advanced” designations refer to the exams rather than to the questions, although in almost all cases, “advanced” questions will be harder. We write questions for the certification exams, and we intend that the same rules apply: Take words at their face value and trust that the questions are not intended to deceive you but to straightforwardly test your knowledge of the ins and outs of the language.
The goal of this quiz is to test your knowledge of the Java Optional
class.
Given the class:
import java.util.Optional;
public class OptionalArgs {
public static void main(String[] args) {
var v = Optional.ofNullable(args[0])
.or(() -> Optional.ofNullable(args[1]))
.flatMap(o -> Optional.empty())
.stream().findFirst().orElse("default");
System.out.print(v);
}
}
What is the output if you run the compiled class as shown below? Choose one.
java OptionalArgs Java
Answer. Let’s work through the steps of execution this Java SE 11 code will perform to determine the result. First, invoke the program with a single command-line argument: Java
. This enters the program through the args
array that is the argument of the main
method. So, args[0]
contains the string "Java"
—and, significantly, it is not null
. Next, the factory method ofNullable
is called with args[0]
as its argument. This constructs an Optional
that contains the string "Java"
.
Next, the code invokes the or
method on the newly created Optional
. The argument to this method is a Supplier<Optional<String>>
, which is invoked if the Optional
is empty. In this way, the or
method can serve to provide a fallback value. However, in this case, the Optional
is not empty, so no fallback value is needed and the Supplier
is not invoked.
Because the Supplier
is not called, the code that would attempt to access args[1]
is not executed, and the ArrayIndexOutOfBoundsException
that would have been thrown is avoided—because only one argument is provided to the program. So far at least, the code is still running normally, and you’re dealing with an Optional
containing "Java"
.
There are two things to note. First, the or
method did not appear until Java 9. Second, the reason the argument to or
in this case is Supplier<Optional<String>>
is because the code indicated that the original Optional
would contain a String
; if that String
is missing, it’s the responsibility of this Supplier
to generate an alternate value wrapped in an Optional
. If the Supplier
produced a value containing something other than String
, it would not be a suitable alternative.
At this point, you have a nonempty Optional
and the code calls flatMap
on it. Because the Optional
is not empty, the value inside the Optional
is passed to the function provided as the argument to the flatMap
call. That function must return some kind of Optional
, which is normal for flatMap
operations, and the content type is permitted to change. In a regular situation, that function would most probably do some processing on the value that is passed to it. In this case, however, the function ignores its argument entirely and simply returns an empty Optional
.
Next, the code creates a stream from the empty Optional
. (Making a stream of either zero elements or one element directly from an Optional
is another feature that was added in Java 9.) Because the stream()
method is called on an empty Optional
, the resulting stream will also be empty and the call to the method findFirst()
that follows it returns another empty Optional
. In effect, the stream()
and findFirst()
calls take you from an Optional
back to another Optional
with the same contents. In this case, the contents are empty.
Finally, the orElse
method is called. This method returns the value contained in the Optional
or, if the Optional
is empty, the value that’s the argument of orElse
. Because the Optional
is empty, the final result will be the argument to orElse
, which is "default"
. Therefore, default
is printed to the console.
The correct answer is option D.
[Find more about Optional
in two articles by Mohamed Taman: 12 recipes for using the Optional class as it’s meant to be used and The Java Optional class: 11 more recipes for preventing null pointer exceptions. —Ed.]