Java 8 – Optional API

During the release of Java 8, one of the major new features of Java 8 is the Optional APIIt is placed in the java.util package in which we also have our List API and so on.

This little guide will help you through the mostly used methods of the Optional API and will teach you the benefits and disadvantages of this new type.

 

Optional

Why exactly do we need Optionals? Developing software in Java can often cause some problems and exceptions. It is no big deal getting exceptions in Java during your development. You´ll learn the best by failure. One of the most common and most hated exception is the NullPointerException. For sure you got them a few times and will get them a few times in your future carrier. Optionals will help you to handle and avoid such NullPointerExceptions.

With value

Let´s create our first Optional. It simply “holds” a String.

We instantiate a String variable and use it to instantiate or Optional with the .of(…) method.

String name = "javadevcorner";
Optional<String> firstOptional = Optional.of(name);

System.out.println(firstOptional);
System.out.println(firstOptional.get());

Output:

Optional[javadevcorner]
javadevcorner

If you run this little piece of code, your Output will look like this. You can see, without calling .get() in the println method the toString method of the Optional is called and we get some “abstract output”.
Just by using the .get() method, we´ll get the value of our Optional.

Without value

What happens if we set our String null? Try it..

String name = null;
Optional<String> firstOptional = Optional.of(name);

NullPointerException …. but I told you, that Optionals beware you of this. Did we do something wrong?
You implemented the best case of a business logic. So we are sure that every time our logic is called, the variable “name” will have a value.

Now let´s implement it the way, that we react to correctly to a null case

String name = null;
Optional<String> firstOptional = Optional.ofNullable(name);

System.out.println(firstOptional);
System.out.println(firstOptional.get());

When you run this piece of code, you´ll still get an exception. But a different one:

Problem of .get() Method

What happened? As you can see, the first Output line worked fine, but the second one crashed. The .get() method is checking, if the value of Optional is null and then throws a NoSuchElementException.

Cause of this, for me, the .get() Method is breaking with the basic concept and idea of the Optional API.

Correct Value handling

After you have seen the major problem of the Optional API, we now can think about how to handle the Optionals more correct.

.isPresent()

One possible solution is the .isPresent() method. You can think about this method like a null check because it is not doing anything else than this. In our example we would modify the second Output line by checking if the value of the Optional is null.

if (firstOptional.isPresent()) {
        System.out.println(firstOptional.get());
}

Your code will no run without a NoSuchElementException. But, as you can see, our new piece of code now looks similiar to the well know null check. So let´s move on and look at the ifPresent() API.

.ifPresent()

Watch out the little difference between isPresent() and ifPresent() !!
While isPresent is returning a boolean, the ifPresent() method allows us to write a Consumer.

For better code quality and better readability I capsule the logic of my consumers to new methods as shown below.

public static void main(String[] args) {

    String name = "javadevcorner";
    Optional<String> firstOptional = Optional.ofNullable(name);
    System.out.println(firstOptional);

    firstOptional
            .ifPresent(optionalValue -> printOut(firstOptional));
}

public static void printOut(Optional optional) {
    System.out.println(optional.get());
}

.orElse()

Another method of the Optional API is the orElse() method. When the value of your Optional is null, this method will return a default value, you have to define.

String name = null;
Optional<String> firstOptional = Optional.ofNullable(name);

System.out.println(firstOptional.orElse("Nothing to present - Default"));

No big deal, isn´t it?

.orElseGet()

You see, there is another alternative for getting our value from an Optional. orElseGet() expects a Supplier and returns something of the inheritance hierarchy of the Supplier. Sounds harder than it actually is. Let´s get it on:

public static void main(String[] args) {

        String name = null;
        Optional<String> firstOptional = Optional.ofNullable(name);
        System.out.println(firstOptional.orElseGet(OptionalExamples::printOutDefault));

    }

public static String printOutDefault() {
        return "Nothing to present - Default";
    }

When you run this little code, your output will be the return of the printOutDefault() method.

Difference between orElse and orElseGet

After you have learned both methods, why should you use the one and not the other? Maybe there are no differences?
Trust me. There is a difference and it´s huge. Let me explain it to you on this little code snipe:

public static void main(String[] args) {
    String name = null;
    
    Optional<String> firstOptional = Optional.ofNullable(name);

    System.out.println("orElse:");
    System.out.println(firstOptional.orElse(printOutDefault()));

    System.out.println("orElseGet:");
    System.out.println(firstOptional.orElseGet(OptionalExamples::printOutDefault));
}

public static String printOutDefault() {
    System.out.println("printOutDefault() call");
    return "Nothing to present - Default";
}

Our Output:

orElse:
printOutDefault() call
Nothing to present - Default
orElseGet:
printOutDefault() call
Nothing to present - Default

Our Output is, how we expected it to be. Isn´t it? We have no value in our Optional and cause of that both, orElse and orElseGet call the default method / logic. 

Let´s change the code a so, that our variable “name” isn´t null anymore. 

//rest of the logic is still the same
      String name = "javadevcorner";
//rest of the logic is still the same

Our Output:

orElse:
printOutDefault() call
javadevcorner
orElseGet:
javadevcorner

Look closely and see what changed.

Executing .orElse() will force the call of the “default way” everytime. No matter if the value of the Optional is null or not.
orElseGet() calls the “default way” only, and really only, when the value of the Optional is null. 

For writing a method that´s just printing out some lines to the console, this won´t be critical. But imagine you have a more complex logic for example handling your database connection in a different way.

 

Summary

You now know the basics about the new Optional API.

We´ve learned how to .get() the value of an Optional and how to check if the value .isPresent() and run a different logic .ifPresent(). 
Furthermore we looked at default behaviours which we can invoke by .orElse(). Because this approach is not the best one, we also discussed the more efficient and effective .orElseGet() approach.

Feel free to share

Leave a Reply

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.