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
Optionalis a way to express that a value might be absent, making code easier to read and maintain. - It is part of the
java.utilpackage.
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
| Feature | Description |
|---|---|
| Definition | A container that may or may not contain a value. |
| Creating Optionals | Use Optional.empty(), Optional.of(), Optional.ofNullable(). |
| Checking Value Presence | Use isPresent() or ifPresent(). |
| Retrieving Values | Use get(), orElse(), orElseGet(), orElseThrow(). |
| Transforming Values | Use 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!