Can someone explain how Optional
helps us avoid NullPointerException
?
Optional<String> op = someFunc()
if(op.isPresent()) {
op.get();
}
String possibleNull = op.get();
Isn't this code prone to NullPointerException
too? If so, then why is this code preferred over
String op = someFunc()
if(op != null) {
op.get();
}
String possibleNull = op;
What possible benefit does Optional
provide other than the fact that it helps us in knowing whether a function actually had a return value or not
The reason why Optionals are so useful is because with Optionals it forces you to represent your data in such a way that you can't invoke a method from null . Without Optionals it's not only possible, it's extremely easy to. In other words, you avoid sloppy logic and stupid errors.
isPresent() method returns true if the Optional contains a non-null value, otherwise it returns false.
In a nutshell, the Optional class includes methods to explicitly deal with the cases where a value is present or absent. However, the advantage compared to null references is that the Optional class forces you to think about the case when the value is not present.
If a value is present, and the value matches the given predicate, returns an Optional describing the value, otherwise returns an empty Optional . If a value is present, returns the result of applying the given Optional -bearing mapping function to the value, otherwise returns an empty Optional .
Let's say you want to get a string returned by a function, convert it to upper case, and then print it out. If you have:
String someFunc() { ... }
You might be tempted to write:
System.out.println(someFunc().toUpperCase());
Of course, this throws NullPointerException
if someFunc
returns null
. Instead, suppose we have this:
Optional<String> someFunc() { ... }
Then
System.out.println(someFunc().toUpperCase());
won't work, since Optional
doesn't have a toUpperCase
method. At this point -- hopefully -- you'll be confronted with an Optional
, which should make you think about the case of the Optional
being empty. This helps avoid NPEs, but probably only somewhat.
Now you might be focusing on how to get the value out of the Optional
, and you might forget about the empty case. Ah, there's a get
method:
System.out.println(someFunc().get().toUpperCase());
This brings back the same problem as NPE, except that the exception is NoSuchElementException
instead. So if you blindly call get
on an Optional
, it really is pretty much the same thing as calling a method on a reference without checking whether it's null.
(For this reason, Brian Goetz considers Optional.get
to be the biggest mistake in Java 8. See his interview with Angelika Langer JAX 2015 Fragen und Antworten zu Java 8 at about 16 minutes in. I'm not sure it's the biggest, but it is a mistake. People just don't expect get
to throw an exception.)
If you're diligent about checking for null references or empty optionals, then
Optional<String> os = someFunc();
if (os.isPresent()) {
System.out.println(os.get().toUpperCase());
}
is hardly any better than the old
String s = someFunc();
if (s != null) {
System.out.println(s.toUpperCase());
}
The real advantage of Optional
is that it's a library class that has a fairly rich API for dealing with the empty case in a safe way. It's often possible to process the value that might be contained within an Optional
by chaining a couple method calls to the method that returned the Optional
in the first place. For example, we could rewrite the sample above as follows:
someFunc().map(String::toUpperCase)
.ifPresent(System.out::println);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With