Optional
PROBLEM
public Foo doSomething() {
return null;
}
Foo foo = doSomething();
if (foo == null) {
// handle null case...
}
else {
// do something with the foo object...
}
SOLUTION
public Optional<Foo> doSomething() {
Optional<Foo> foo = Optional.of(new Foo()); // populated Optional
Optional<Foo> foo = Optional.of(null); // throws NullPointerException
// Right way
Optional<Foo> foo1 = Optional.ofNullable(new Foo()); // populated Optional
Optional<Foo> foo2 = Optional.ofNullable(null); // empty Optional
Optional<Foo> populated = // ...populated Optional...
populated.isPresent(); // true
populated.isEmpty(); // false
}
Foo foo = doSomething()
.orElse(new Foo());
Foo foo = doSomething()
.orElseThrow(SomeException::new);
// we must use additional methods
Foo foo = doSomething(); // - will not compile
Optional<Foo> possibleFoo = doSomething();
Foo foo = possibleFoo
.orElseGet(() -> { /* ...lazily create a Foo object... */ });
possibleFoo.ifPresent(foo -> { /* ...do something with foo... */ });
possibleFoo.ifPresentOrElse(
foo -> { /* ...do something with foo... */ },
() -> { /* ...do something when no foo found... */ }
);
// for Example
public Optional<Bar> findBar() {
// ...return a populated Bar if it could be found...
}
findBar().ifPresent(bar -> bar.update());
If a null value is returned in place of an Optional object, this is a breach of the method contract on the part of the method developer. By stating that a method will return an Optional object, the method developer is also stating that it is invalid to return null. Since the Optional object denotes the possibility of a missing object, there is no valid use case for a null value (i.e., the method should return an empty Optional instead of null in all cases).
Therefore, whenever we are dealing with an Optional object, we are right to assume that the Optional object will never be null. Although it is possible that the Optional object can be null in practice, this is a problem that should be resolved by the method developer rather than the client.