Optional.of() and Optional.ofNullable()

Wrap a value in an Optional, choosing of() when null is a bug and ofNullable() when null means the value is genuinely absent.

Signature
public static <T> Optional<T> of(T value)
public static <T> Optional<T> ofNullable(T value)
  • Added in Java Java 8

Parameters

ParameterTypeDescription
$valueTThe value to wrap. Must not be null for of(); may be null for ofNullable().

Return value

Optional<T>of() returns an Optional holding the given non-null value. ofNullable() returns an Optional holding the value, or an empty Optional if the value is null.

Errors

Optional.of throws NullPointerException if value is null. Optional.ofNullable never throws.

Optional is a container that holds either one non-null value or nothing. Its main job is to be the return type of a method that might not have an answer, such as findById, so the caller cannot forget the not-found case. The two factory methods differ only in how they treat null.

Which one to call

Optional.of(value) requires a value. Passing null throws NullPointerException immediately. Use it when you have just created or checked the value and a null there would mean a bug in your own code; the exception points straight at it.

Optional.ofNullable(value) accepts null and turns it into Optional.empty(). Use it at the edges where null is the normal way older APIs say "not there": Map.get, HttpServletRequest.getHeader, a nullable database column, System.getenv.

Optional<User> findById(long id) {
    return Optional.ofNullable(usersById.get(id)); // Map.get returns null when missing
}

Mistakes people make

  • Calling Optional.of(map.get(key)). It works in every test with known keys, then throws in production the first time a key is missing. If the value can be absent, it is ofNullable.
  • Returning null from a method declared to return Optional. Callers will chain .map(...) and get a NullPointerException on the Optional itself. Return Optional.empty() instead.
  • Using Optional for fields, method parameters or collection elements. It is not Serializable, it adds an allocation, and an empty list or a nullable parameter says the same thing more simply. Keep it for return values.

Back-end angle

Repository and service methods that look one thing up are the natural home for Optional. Spring Data's findById returns Optional<T> for exactly this reason. A controller then turns the empty case into a 404 with orElseThrow, rather than every layer checking for null. For primitives there are OptionalInt, OptionalLong and OptionalDouble, which avoid boxing.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Returning the result of a repository lookup by id so the controller must decide what a missing row means.
  • Wrapping an optional HTTP header or query parameter read from a map that returns null for missing keys.
  • Turning a nullable database column or environment variable into a value that can be defaulted or validated in one chain.

Frequently asked questions

What is the difference between Optional.of and Optional.ofNullable?

Optional.of(value) throws NullPointerException if value is null, so it is for values that must exist. Optional.ofNullable(value) returns Optional.empty() for null and is for values that may legitimately be missing.

Why does Optional.of throw a NullPointerException?

Because you passed it null. Optional.of is designed to fail fast when a value you claim is present is not. If null is a normal outcome, such as a missing map key, use Optional.ofNullable instead.

Should I use Optional as a method parameter or field?

Generally no. Optional was designed as a return type. It is not Serializable, so it does not suit entity or DTO fields, and an Optional parameter forces callers to wrap values. Overloads or a nullable parameter with a clear contract are simpler.

More examples

Wrapping a request header that may be missing

Map.get returns null for a missing header, and ofNullable turns that into an empty Optional so orElse can supply a fallback. With Optional.of the second call would throw.

Example · java
String requestId(Map<String, String> headers) {
    return Optional.ofNullable(headers.get("X-Request-Id"))
            .orElse("generated-0001");
}

void main() {
    IO.println(requestId(Map.of("X-Request-Id", "abc-123")));
    IO.println(requestId(Map.of("Accept", "application/json")));
}
// Output:
// abc-123
// generated-0001

Using of() when the value is known to exist

Integer.parseInt never returns null, so of() is the honest choice there; the empty cases are handled explicitly with Optional.empty(). This is the shape of a typical parse-or-nothing helper for configuration values.

Example · java
Optional<Integer> parsePort(String raw) {
    if (raw == null || raw.isBlank()) {
        return Optional.empty();
    }
    try {
        return Optional.of(Integer.parseInt(raw.strip()));
    } catch (NumberFormatException e) {
        return Optional.empty();
    }
}

void main() {
    IO.println(parsePort("8080"));
    IO.println(parsePort(" 9000 "));
    IO.println(parsePort("abc"));
    IO.println(parsePort(null));
}
// Output:
// Optional[8080]
// Optional[9000]
// Optional.empty
// Optional.empty

Equality, hashCode and toString

Two Optionals are equal when both are empty or both hold equal values, regardless of which factory made them. The hash code is the value's hash code, or 0 when empty.

Example · java
void main() {
    Optional<String> a = Optional.of("json");
    Optional<String> b = Optional.ofNullable("json");
    Optional<String> none = Optional.ofNullable(null);

    IO.println(a.equals(b));
    IO.println(none.equals(Optional.empty()));
    IO.println(Optional.of(42).hashCode() + " " + none.hashCode());
    IO.println(a + " " + none);
}
// Output:
// true
// true
// 42 0
// Optional[json] Optional.empty

Discussion

  • Be the first to comment on this lesson.