Skip to main content

8. Optionals in Java

Optional is a container object introduced in Java 8 that may or may not contain a non-null value. It helps in avoiding null references and the associated NullPointerException.

1. What is an Optional?

  • An Optional is a way to express that a value might be absent, making code easier to read and maintain.
  • It is part of the java.util package.

2. Creating Optional Instances

You can create an Optional instance using the following methods:

2.1. Optional.empty()

Creates an empty Optional instance.

Optional<String> emptyOptional = Optional.empty();

2.2. Optional.of(T value)

Creates an Optional with a non-null value. If the value is null, it throws a NullPointerException.

Optional<String> nonNullOptional = Optional.of("Hello");

2.3. Optional.ofNullable(T value)

Creates an Optional that can contain a null value. If the value is null, it returns an empty Optional.

Optional<String> nullableOptional = Optional.ofNullable(null); // Empty Optional

3. Checking for Presence of Value

You can check if an Optional contains a value using:

3.1. isPresent()

Returns true if there is a value present, otherwise false.

if (nonNullOptional.isPresent()) {
System.out.println(nonNullOptional.get()); // Prints "Hello"
}

3.2. ifPresent(Consumer<? super T> action)

Executes the given action if a value is present.

nonNullOptional.ifPresent(value -> System.out.println(value)); // Prints "Hello"

4. Retrieving Values

You can retrieve the value stored in an Optional using:

4.1. get()

Returns the value if present; otherwise, it throws NoSuchElementException.

String value = nonNullOptional.get(); // "Hello"

4.2. orElse(T other)

Returns the value if present; otherwise, returns the provided default value.

String valueOrDefault = nullableOptional.orElse("Default Value"); // "Default Value"

4.3. orElseGet(Supplier<? extends T> other)

Returns the value if present; otherwise, invokes the provided supplier and returns its result.

String valueOrElseGet = nullableOptional.orElseGet(() -> "Generated Value"); // "Generated Value"

⚠️ By default, it makes more sense to use orElseGet() every time, unless the default object is already constructed and directly accessible. It is better performance-wise !

4.4. orElseThrow(Supplier<? extends X> exceptionSupplier)

Returns the contained value if present; otherwise, throws an exception generated by the provided supplier.

String valueOrThrow = nullableOptional.orElseThrow(() -> new IllegalArgumentException("Value is missing"));

5. Transforming Values

You can transform the value in an Optional using:

5.1. map(Function<? super T,? extends U> mapper)

Applies a function to the value if present and returns a new Optional containing the transformed value.

Optional<Integer> lengthOptional = nonNullOptional.map(String::length); // Optional containing 5

5.2. flatMap(Function<? super T, Optional<U>> mapper)

Similar to map, but the function must return an Optional. It flattens the nested Optional.

Optional<String> upperOptional = nonNullOptional.flatMap(value -> Optional.of(value.toUpperCase())); // Optional containing "HELLO"

6. Summary of Optionals

FeatureDescription
DefinitionA container that may or may not contain a value.
Creating OptionalsUse Optional.empty(), Optional.of(), Optional.ofNullable().
Checking Value PresenceUse isPresent() or ifPresent().
Retrieving ValuesUse get(), orElse(), orElseGet(), orElseThrow().
Transforming ValuesUse map() and flatMap().

💡 Optionals are an important addition to Java that helps in reducing null-related errors and improving code readability. If you have any further questions or need additional examples, feel free to ask!