Java8 Optional API

Reading Time: 3 minutes

Lets understand the use of Optional with a small real example in a production code to understand the real power of Optional

Suppose you want to get the value from an environment variables and want to set a default value if value is not present instead of throwing NullPointer Exception. In a traditional way we would write

private static String getPropertyOrThrow(String propertyName) throws IllegalArgumentException {
    String value = System.getProperty(propertyName);
    if (value == null) {
        value = System.getenv(propertyName);
    }
    if (value != null) {
        return value;
    }
    throw new IllegalArgumentException("`" + propertyName + "` property not defined.");
}

With Optional we can write the same code as follows

public static String getPropertyOrDefault(String propertyName, String defaultValue) {
    return Optional.ofNullable(System.getProperty(propertyName)).orElse(defaultValue);
}

See how easy it is to write the above code in just 1 line. Looking at this now you might have one question

What is Optional ?

Java 8 introduced a new class java.util.Optional<T> which encapsulates a value. A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value. It prevents any NullPointerExceptions runtime and helps us build clean and tidy Java APIs or Applications. Like Collections and arrays, it is also a Container to hold at most one value.

Different ways to create Optional are:

  1. Optional.empty() – This method will return an empty Optional object.
    Optional card = Optional.empty();
  2. Optional.of() – This method will return an Optional of object passed as an argument to the of method. Returns an Optional with the specified present non-null value.
    Optional value = Optional.of(System.getProperty(propertyName));
  3. Optional. ofNullable() – Returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional
    Optional value = Optional.ofNullable(System.getProperty(propertyName));;

Difference between .of and .ofNullable ?

Optional.of() will return the object of Optional without null check. It means if there is no value present it will return null. The method to define .of() is

public static <T> Optional<T> of(T var0) {
    return new Optional(var0);
}

Optional.ofNullable() will return the object of Optional with a null check. If this method gets the null as an input then it will return the empty Optional otherwise it returns an Optional with the specified present non-null value. The method to define .ofNullable() is

public static <T> Optional<T> ofNullable(T var0) {
    return var0 == null ? empty() : of(var0);
}

Optional.of() will be used when you are confident the Optional will never have a null object and it will either contain the value of the object or it will be empty but not null. Optional.of() can also throw a NullPointerEception if a null value for the Optional is generated.
Optional.ofNullable()- is used in situations where the value is likely to be null.

Methods available in Optional

.isPresent() – This method returns true if the object is present into an Optional object.

.orElse(T other) – Return the value if present, otherwise returns the object passed as a parameter. Internals of orElse(0 method in Java 8 Optional class.

.orElseThrow(Supplier exceptionSupplier) – Return the contained value, if present, otherwise throw an exception to be created by the provided supplier.

.get() – If a value is present in this Optional, returns the value, otherwise throws NoSuchElementException.

.ifPresent() – It performs given action if the given Optional object is non-empty. Otherwise it returns false.

.map() – If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional.

.filter() – If a value is present, and the value matches the given predicate, return an Optional describing the value, otherwise return an empty Optional.

Where can Java Optional be used

Method Return Types
public Optional<TestCaseDetail> initiateTest(testInfo testCase) throws Exception

Declaration of Variables
private Optional<String> value ;

Instance fields – Use plain values. Optional wasn’t created for usage in fields. It’s not serializable and adds a wrapping overhead that you don’t need. Instead, use them on the method when you process the data from the fields.
Method parameters – Use plain values. Dealing with tons of Optionals pollutes the method signatures and makes the code harder to read and maintain. All functions can be lifted to operate on optional types where needed. Keep the code simple!

References:

https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html

Knoldus-blog-footer-image