tl;dr
The code you showed saying “I know this doesn't compile” actually should compile. That code is your solution.
Using similar code, see this method:
public Optional < DayOfWeek > getFavoriteDayOfWeek ( )
{
return Optional.ofNullable( DayOfWeek.WEDNESDAY ); // Silly implementation for demonstration.
}
…called like this:
this.getFavoriteDayOfWeek().ifPresent(
( DayOfWeek dow ) -> { … dow.get() … }
);
…run live successfully at IdeOne.com.
Keep in mind that an Optional
is its own object, wrapping some other object as its payload. So be careful about your type declarations: Optional<DayOfWeek> someVar
versus DayOfWeek someVar
.

Return the Optional
If a null is an acceptable value in your domain, then return the Optional
. Returning a null
unwrapped from within an Optional
defeats the purpose of an Optional
.
The purpose of an Optional
is to signal to the calling method that a null is indeed a valid possibility. The type system of Java is being used to remind the calling programmer to code for the possibility of a null
. An Optional
object is like a big safety-orange traffic sign saying: “Beware: possible NULL ahead”.
Returning just null
unwrapped from within an Optional
adds no value, and makes for brittle code.
The code shown in the Question is jumping through extra hoops needlessly, just introducing an extra level of indirection with no benefit. The calling method should indeed receive an Optional
if a payload of null
is a valid result.
So this:
//in class Bar
public Foo getFooIfItIsPresent(String param) {
Optional<Foo> result = loadOptionalFoo(param);
if (result.isPresent()) {
return result.get();
} else {
return null;
}
// main driver code
Foo foo = Bar.getFooIfItIsPresent(param);
if (foo != null) {
// Currently just print, but might want to do stuff like pass foo to another object, etc.
System.out.println(foo.getSomething() + foo.getSomethingElse());
}
…should be:
//in class Bar
// ➥ Delete this method `getFooIfItIsPresent`. Adds no value.
// public Foo getFooIfItIsPresent(String param)
…and…
// main driver code
Optional<Foo> result = someBar.loadOptionalFoo( param );
if ( result.isPresent() ) {
// Currently just print, but might want to do stuff like pass foo to another object, etc.
Foo foo = result.get() ; // Calling `get` is safe because we checked for null in the `if … isPresent` line above.
System.out.println( foo.getSomething() + foo.getSomethingElse() ) ;
}
Notice how we call Optional::get
only after checking for null by calling Optional::ifPresent
.
The Optional
class offers various methods if you want to address the if else
condition where the Optional
is empty with no Foo
object present. See methods such as orElse
, orElseGet
, and orElseThrow
.
Your problematic code should indeed compile
You said this code does not compile:
Bar.loadOptionalFoo(param).ifPresent((foo) -> {
// Print, or whatever I wanna do!
System.out.println(foo.getSomething() + foo.getSomethingElse());
});
Actually, that code should compile. It is perfectly reasonable to do, another variation of what I showed as a solution above.
Here is a similar example. I make the method getFavoriteDayOfWeek
which returns an Optional< DayOfWeek >
using the DayOfWeek
enum class built into Java. If a favorite day is registered, the method returns an Optional
holding a DayOfWeek
object. If no favorite has yet been determined, the method returns an empty Optional
. Here is our dummy version of that method.
public Optional < DayOfWeek > getFavoriteDayOfWeek ( )
{
return Optional.ofNullable( DayOfWeek.WEDNESDAY );
}
Calling that method using code similar to your code:
this.getFavoriteDayOfWeek().ifPresent(
( DayOfWeek dayOfWeek ) -> {
// Print, or whatever I wanna do!
System.out.println( dayOfWeek.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH ) );
}
);
When run:
mercredi
INFO - Done running demo.
You can change the WEDNESDAY
object with null
to experiment.
public Optional < DayOfWeek > getFavoriteDayOfWeek ( )
{
return Optional.ofNullable( null );
}
When run, we see that the System.out.println( dayOfWeek.getDisplayName(…
code is never called because the conditional test for our Optional<DayOfWeek>
actually containing a DayOfWeek
object (ifPresent
) was not met. We see output only from our second System.out.println
, for "Done running".
INFO - Done running demo.
See this code run live at IdeOne.com.
Making an Optional
The body of your Question seems to be asking about extracting a value from an Optional
. I showed that above.
The title of your Question seems to be about wrapping a value in an Optional
.
- If you know you want to return a
null
, return Optional.empty()
.
- If returning something that may or may not be null, return
Optional.ofNullable( x )
.
- If returning something that should definitely not be null in that situation, return
Optional.of( x )
. That method throws NullPointerException
if the value is null. Use this method when the presence of a null means something went very wrong with your app.
A tip, by the way, after seeing your use of if (foo != null) {
:
If you do need to test for a null
, I suggest instead of using x != null
or x == null
that you instead use the Objects
class methods, Objects.nonNull( Object obj )
and Objects.isNull( Object obj )
, respectively.
Even better, in a situation where the presence of a null in intolerable, meaning a major unexpected failure in your code, call Objects.requireNonNull( T obj )
. This method throws NullPointerException
if receiving a null. Even better, this method returns the object passed. This makes it perfect for assigning passed arguments to other variables.
public void doSomething( final Fruit fruit , final DayOfWeek dayOfWeek )
{
this.fruit = Objects.requireNonNull( fruit ) ;
this.dayOfWeek = Objects.requireNonNull( dayOfWeek ) ;
}
Last tip: Java 14 brings more helpful NullPointerException
objects, better pinpointing the place of failure. See JEP 358: Helpful NullPointerExceptions.