Avoiding Null Checks in Java: When to Use Assertions, Exceptions, and the Null Object Pattern
The article explains why excessive null‑checking in Java code is problematic, distinguishes between null as a valid response and as an error, and offers practical techniques such as assertions, throwing exceptions, returning empty collections, and applying the Null Object pattern to write cleaner, safer backend code.
To prevent the proliferation of null‑checking statements that clutter Java projects, the article first points out that developers often write if (someObject != null) { someObject.doCalc(); } and end up with repetitive, ugly code.
It then separates two scenarios: (1) null is a meaningful, valid return value according to the method contract, and (2) null indicates an invalid or erroneous situation that should abort execution.
For the second case, the author recommends using assert statements with explanatory messages or directly throwing a NullPointerException to signal that a required argument is missing, especially in API methods where a null parameter is unacceptable.
When null is a legitimate response, the article suggests returning an empty collection instead of null, allowing callers to safely invoke methods like list.size() without additional checks. If the return type is not a collection, returning an empty object (a "null object") is advised.
The Null Object pattern is illustrated with the following code:
public interface Action {
void doSomething();
}
public interface Parser {
Action findAction(String userInput);
}and a concrete implementation that never returns null :
public class MyParser implements Parser {
private static Action DO_NOTHING = new Action() {
public void doSomething() { /* do nothing */ }
};
public Action findAction(String userInput) {
// ...
if (/* we can't find any actions */) {
return DO_NOTHING;
}
// otherwise return a real Action
}
}Two usage examples compare a verbose null‑check approach with a concise chained call:
Parser parser = ParserFactory.getParser();
if (parser == null) {
// now what?
}
Action action = parser.findAction(someInput);
if (action == null) {
// do nothing
} else {
action.doSomething();
} ParserFactory.getParser().findAction(someInput).doSomething();Because the refactored findAction never returns null , the caller can safely invoke doSomething() without defensive checks.
Additional recommendations include using the constant‑first form of equals (e.g., "bar".equals(foo) ) to avoid NullPointerException , leveraging Java 8/Guava Optional to encapsulate possibly‑null values, and considering throwing an exception instead of returning null when appropriate.
Overall, the article provides a practical guide for Java backend developers to reduce null‑related boilerplate, improve code readability, and adopt safer design patterns.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.