Should functions return null or an empty object?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Whether a function should return null or an empty object depends on what the return value means in the domain. The real question is not style but semantics: are you expressing "there is no result," or are you expressing "the result exists, but it contains no items". If you treat those two cases as the same, your API becomes harder to reason about.
Use null Only for True Absence
Return null when the value genuinely may not exist. A typical example is looking up a single entity by ID.
In this API, null means "there is no such user." That is a meaningful state, not just an empty container.
The downside is that callers must handle it explicitly:
That is acceptable when absence is part of the contract. It is a problem when callers need defensive null checks everywhere because the function design was vague.
Return Empty Collections for Zero Items
If a function returns a collection, zero items is usually not the same as "no result." In that case, returning an empty collection is almost always the better contract.
Now callers can iterate safely without branching on null:
That is cleaner because the meaning is precise: the team exists as a query target, but currently no users match.
Consider an Explicit Optional Type
For single optional values, a wrapper type is often clearer than null. In modern Java, Optional makes the contract visible at the type level.
Usage becomes explicit:
This avoids ambiguous null values and makes absence part of the API rather than an undocumented convention.
Empty Objects Are Useful Only When They Mean Something
Sometimes returning an empty object is correct, but only if that object is still a valid domain value. For example, a shopping cart with zero items is still a real cart.
This works because an empty cart is meaningful. It does not mean the user was missing or the lookup failed. It means the cart exists and is currently empty.
The pattern becomes dangerous when the empty object hides an error. If a payment lookup fails because the database is unavailable, returning a blank Payment object would be misleading. That is not "empty data"; that is a failure state.
A Simple Decision Rule
Use this rule when designing the return type:
- return an empty collection when the answer is "zero items"
- return
nullor an optional type when the answer is "no such value" - throw an exception or return an error result when the operation failed
Those three cases should not collapse into one return value. If they do, callers cannot distinguish normal emptiness from absence or failure.
Common Pitfalls
- Returning
nullfor collections, which forces callers to write unnecessary null checks. - Returning an empty object when the function actually failed.
- Using
nullwithout documenting whether it means "not found" or "not computed". - Treating an optional single value the same way as a list of zero results.
- Picking one convention inconsistently across similar APIs in the same codebase.
Summary
- Return
nullonly when absence of a single value is a valid outcome. - Return empty collections when the result is simply "zero items".
- Use
Optionalor an equivalent type when you want absence to be explicit in the type system. - Return empty objects only if they are genuine domain values, not disguised failures.
- Keep absence, emptiness, and errors as separate concepts in your API design.

