A bit of Java 8 Optional<T>

For me Java 8 wasn’t a big deal … until I had to go back to Java 7. Suddenly I started missing things I started using without even realizing it. Here comes Optional<T>:

Assume we have some sort of class (Provider) which does something and has a “getName” method. Now we also have a method in a class managing providers which returns the provider by id, so we pass in a string ID and get back a provider:

[code language=”Java”]
static class Provider {
String getName () {
return "bar";
}
}

static Provider getProvider ( final String id ) {
if ( "foo".equals ( id ) ) {
return new Provider ();
}
return null;
}
[/code]

In this simple example the manager only knows the provider “foo”, which will return “bar” as its name. All requests for other providers will return null. A real life scenario might have a Map, which also returns null in case of a missing element.

Now a pretty common code snippet before Java 8 would look like this:

[code language=”Java”]
final Provider provider = getProvider ( "bar" );
final String value;
if ( provider != null ) {
value = provider.getName ();
} else {
value = null;
}
System.out.println ( "Bar (pre8): " + value );
[/code]

Pretty noisy. So the first step is to use the “Optional” type, and to guarantee that the getProvider method never returns null. So we don’t have to check for it:

[code language=”Java”]
static Optional<Provider> getOptionalProvider ( final String id ) {
return Optional.ofNullable ( getProvider ( id ) );
}
[/code]

In this case a new method was added, which simply calls the old one. The next thing is to use Optional.map(…) and Optional.orElse(…) to transform the value and return a default if we don’t have a value.

[code language=”Java”]
String value1 = getOptionalProvider ( "foo" )
.map ( Provider::getName )
.orElse ( null );
System.out.println ( "Foo: " + value1 );
[/code]

Pretty simple actually. But still readable and understandable (although some people might disagree on that one ;-) ).

So what does happen? First the call to getOptionalProvider will now never return null. If the value itself would be null, it would return an empty Optional but still a class instance. Actually always the same, since there is only one instance of an empty Optional. Next the map method will call the provided expression (longer version would be: value -> value.getName()), but the method will only do this if the Optional is not empty. Otherwise it will return an empty Optional again. So after calling map we either have an Optional<String> with the value of getName(), or again an empty Optional. Calling orElse on this new Optional will either return the value of the Optional or the default value provided, null in this case.

Of course one could argue that internally the same logic happens as with Java 7 and before. But I think that this way, you actually can do a one-liner which is understandable but still does not obstruct the your actual class with to many lines of code just or checking about null.

Full sample:
[code language=”Java”]
import java.util.Optional;

public class Manager
{

static class Provider
{
String getName ()
{
return "bar";
}
}

static Provider getProvider ( final String id )
{
if ( "foo".equals ( id ) )
{
return new Provider ();
}
return null;
}

static Optional<Provider> getOptionalProvider ( final String id )
{
return Optional.ofNullable ( getProvider ( id ) );
}

public static void main ( final String[] args )
{
final String value1 = getOptionalProvider ( "foo" ).map ( Provider::getName ).orElse ( null );
System.out.println ( "Foo: " + value1 );

final String value2 = getOptionalProvider ( "bar" ).map ( Provider::getName ).orElse ( null );
System.out.println ( "Bar: " + value2 );

// before Java 8

final Provider provider = getProvider ( "bar" );
final String value3;
if ( provider != null )
{
value3 = provider.getName ();
}
else
{
value3 = null;
}
System.out.println ( "Bar (pre8): " + value3 );
}
}
[/code]

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.