Objects.requireNonNullElse()
Swap a null for a default value in one call, with requireNonNullElseGet when the default is costly to create.
public static <T> T requireNonNullElse(T obj, T defaultObj)
public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)- Added in Java Java 9
Parameters
| Parameter | Type | Description |
|---|---|---|
$obj | T | The value to use if it is not null. |
$defaultObj | T | The fallback for requireNonNullElse. Evaluated before the call, and must not be null. |
$supplieroptional | Supplier<? extends T> | For requireNonNullElseGet: called only when obj is null, and must return a non-null value. |
Return value
Tobj if it is not null; otherwise defaultObj (or the supplier's result), which must itself be non-null.
Errors
NullPointerException if obj and defaultObj are both null, or, for requireNonNullElseGet, if obj is null and the supplier is null or returns null.
Java has no ?? operator. Objects.requireNonNullElse(value, fallback) is the closest thing in the JDK: it returns value if it is not null and fallback otherwise. The name sounds like a check, but its job is defaulting; the "require" part is that the result is guaranteed non-null.
When to use it
Any time a nullable value from outside needs a sensible default: an optional query parameter, a JSON field the client left out, a nullable column, a configuration entry. It reads better than a ternary and does not evaluate the value expression twice.
int pageSize = Integer.parseInt(
Objects.requireNonNullElse(params.get("size"), "20"));
List<String> tags = Objects.requireNonNullElse(body.tags(), List.of());Else versus ElseGet
Arguments in Java are evaluated before the call, so requireNonNullElse(cached, loadFromDatabase()) runs the query every time, even when cached is present. requireNonNullElseGet(cached, () -> loadFromDatabase()) only calls the supplier when it is needed. Constants and literals belong in the first form; anything that allocates, queries or computes belongs in the second.
Mistakes people make
- Passing a default that can itself be null. If both are null the method throws
NullPointerException. If null is an acceptable result, use a plain ternary instead. - Expecting it to treat empty strings as missing.
requireNonNullElse("", "20")returns"". A query string like?size=gives an empty value, not null, so handle blanks separately. - Wrapping in
Optionaljust to default a value.Optional.ofNullable(x).orElse(d)works, but allocates and says more than you mean. KeepOptionalfor return types and use this for plain defaulting.
Back-end angle
Normalising request DTOs is the main use. Replacing null collections with empty ones early means the rest of the service can loop and stream without null checks, and replacing missing paging values with defaults keeps queries bounded. For Map lookups, getOrDefault does the same job when the key is absent.
Example
When to use it
- Filling in default page number and page size when a list endpoint is called without paging parameters.
- Replacing a null list in an incoming JSON body with an empty list so later code can loop without null checks.
- Using a configured value if present and an expensive computed default, via requireNonNullElseGet, only when it is missing.
Frequently asked questions
Does Java have a null coalescing operator like ?? in C# or JavaScript?
No. Objects.requireNonNullElse(a, b) is the JDK method that does the same job, and requireNonNullElseGet defers building the default.
What is the difference between requireNonNullElse and Optional.orElse?
They return the same thing when the default is non-null. requireNonNullElse works on a plain value without creating an Optional and throws if the default is null, while Optional.orElse accepts a null default.
Why does requireNonNullElse throw a NullPointerException?
Because both the value and the default were null. The method promises a non-null result, so it rejects a null default.
More examples
Else evaluates the default, ElseGet does not
The first call loads the default even though a saved value exists. With requireNonNullElseGet the supplier only runs when the value is actually null.
int loads = 0;
String loadDefaultTheme() {
loads++;
return "light";
}
void main() {
String saved = "dark";
String a = Objects.requireNonNullElse(saved, loadDefaultTheme());
IO.println(a + ", loads=" + loads);
String b = Objects.requireNonNullElseGet(saved, this::loadDefaultTheme);
IO.println(b + ", loads=" + loads);
String c = Objects.requireNonNullElseGet(null, this::loadDefaultTheme);
IO.println(c + ", loads=" + loads);
}
// Output:
// dark, loads=1
// dark, loads=1
// light, loads=2Empty strings are not null
A missing parameter is null and gets the default, but ?size= arrives as an empty string and passes straight through. The blank check covers that second case.
int pageSize(Map<String, String> query) {
String raw = Objects.requireNonNullElse(query.get("size"), "20");
return raw.isBlank() ? 20 : Integer.parseInt(raw.strip());
}
void main() {
IO.println(pageSize(Map.of("size", "50")));
IO.println(pageSize(Map.of()));
IO.println(pageSize(Map.of("size", "")));
}
// Output:
// 50
// 20
// 20Both null throws
The method guarantees a non-null result, so a null default is rejected. When null is a valid outcome, a plain ternary is the honest choice.
void main() {
String configured = null;
String fallback = null;
try {
Objects.requireNonNullElse(configured, fallback);
} catch (NullPointerException e) {
IO.println("NullPointerException: " + e.getMessage());
}
String region = configured != null ? configured : fallback;
IO.println(region);
}
// Output:
// NullPointerException: defaultObj
// null
Discussion