Optional Class in Java
The Optional class in Java, in java.util, is a container object that may or may not contain a value. It is used as the return type of a method that might have no result, such as "find the student named Navika", instead of returning null. An Optional makes the possibility of "nothing" visible in the method's signature, so callers can't forget to handle it. Optional was added in Java 8. In this lesson, you will learn how to create an Optional and how to read its value safely.
Declaration
public final class Optional<T>Creating an Optional
| Method | Description |
|---|---|
Optional.of(value) | It creates an Optional with a value; throws if the value is null. |
Optional.ofNullable(value) | It creates an Optional that is empty if the value is null. |
Optional.empty() | It creates an empty Optional. |
Methods of Optional
| Method | Description |
|---|---|
isPresent() / isEmpty() | It checks whether a value is there (isEmpty since Java 11). |
get() | It returns the value; throws NoSuchElementException if empty. |
orElse(other) | It returns the value, or other if empty. |
orElseGet(supplier) | It returns the value, or calls the supplier if empty. |
orElseThrow() | It returns the value, or throws NoSuchElementException (Java 10). |
orElseThrow(supplier) | It returns the value, or throws the exception you supply. |
ifPresent(consumer) | It runs the action only if a value is there. |
ifPresentOrElse(consumer, runnable) | It runs one action or the other (Java 9). |
map(function) | It transforms the value if present. |
flatMap(function) | It transforms with a function that itself returns an Optional. |
filter(predicate) | It keeps the value only if it passes the test. |
or(supplier) | It returns this Optional, or another Optional if empty (Java 9). |
stream() | It returns a stream of zero or one element (Java 9). |
Example: Returning Optional from a Search
Let's see an example of a method that might not find a student.
import java.util.List;
import java.util.Optional;
public class FindStudent {
record Student(String name, int marks) { }
static final List<Student> STUDENTS = List.of(
new Student("Navika", 91), new Student("Srihitha", 78));
static Optional<Student> find(String name) {
return STUDENTS.stream()
.filter(s -> s.name().equals(name))
.findFirst();
}
public static void main(String[] args) {
Optional<Student> found = find("Navika");
Optional<Student> missing = find("Advitha");
System.out.println(found.isPresent() + " " + missing.isPresent());
System.out.println(found.get().marks());
System.out.println(missing.map(Student::marks).orElse(0));
found.ifPresent(s -> System.out.println("Found " + s.name()));
missing.ifPresentOrElse(
s -> System.out.println("Found " + s.name()),
() -> System.out.println("Advitha is not in the list"));
}
}true false
91
0
Found Navika
Advitha is not in the listExplanation: find returns an Optional<Student>: full when the name exists, empty when it doesn't. get() is safe here only because we know Navika was found. For the missing student, map(Student::marks).orElse(0) gives 0 instead of crashing. ifPresentOrElse handles both cases neatly.
Example: Transforming an Optional
import java.util.Optional;
public class Transform {
public static void main(String[] args) {
Optional<String> name = Optional.of(" navika ");
String result = name
.map(String::strip)
.filter(n -> n.length() > 3)
.map(String::toUpperCase)
.orElse("UNKNOWN");
System.out.println(result);
Optional<String> blank = Optional.ofNullable(null);
System.out.println(blank.map(String::toUpperCase).orElse("UNKNOWN"));
try {
Optional.of(null);
} catch (NullPointerException e) {
System.out.println("Optional.of(null) throws");
}
}
}NAVIKA
UNKNOWN
Optional.of(null) throwsExplanation: map and filter work like their stream versions but on at most one value. If the Optional is empty at any step, the rest is skipped and orElse supplies the default. ofNullable(null) gives an empty Optional, while of(null) throws.
Common Mistakes
Calling get() without checking. It throws NoSuchElementException when empty; use orElseThrow() if that's intended, so it reads as deliberate.
Using Optional.of with a value that might be null. Use ofNullable.
Writing if (opt.isPresent()) { x = opt.get(); }. It's just a null check in disguise; use map, orElse or ifPresent.
Interview Corner
What is Optional, and why was it introduced?
Optional<T> is a container that holds either a value or nothing. It was added in Java 8 mainly as a return type for methods that may have no result, so the possibility of absence is explicit in the API and callers are pushed to handle it, instead of receiving null and risking a NullPointerException. It offers methods like orElse, orElseGet, orElseThrow, map, filter and ifPresent to work with the value safely.
What is the difference between orElse and orElseGet?
orElse(value) takes an already-computed value, which is evaluated every time, even if the Optional has a value. orElseGet(supplier) takes a supplier that is called only when the Optional is empty. Use orElseGet when the default is expensive to compute.
Practice
- Easy: Write a method
Optional<Integer> parse(String s)that returns the number, or an emptyOptionalif the string isn't a valid integer. - Harder: Using
parse, convert a list of strings into the sum of the valid numbers only, usingflatMap(Optional::stream).
Key Takeaways
Was this tutorial helpful?