Fundamentals 7 min read

When Is Null Checking Overkill? Smart Strategies to Eliminate Redundant Checks

This article examines why excessive null‑checking clutters code, distinguishes when null is a valid response versus an error, and offers practical alternatives such as assertions, exceptions, returning empty collections, and the Null Object pattern to write cleaner, safer Java programs.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
When Is Null Checking Overkill? Smart Strategies to Eliminate Redundant Checks

Hello, I'm Penglei!

To avoid null‑pointer calls we often see code like:

if (someobject != null) {
    someobject.doCalc();
}

In large projects this leads to a lot of repetitive and ugly null‑checking.

How can we avoid this? Have we overused null checks?

Key answer: This is a common issue for junior developers who frequently return null from methods, forcing callers to perform null checks. Many also assume that all returns are untrustworthy and add excessive checks.

Before checking for null, distinguish two situations:

Null is a valid, meaningful return value according to the contract.

Null is an invalid response (e.g., an unreasonable argument).

In the second case, treat null as an error: either use an assert statement with a clear message or throw a NullPointerException to signal the problem.

In the first case, null often represents an “empty” concept, such as a database query that finds no matching record.

Practical suggestions:

If a method returns a collection, return an empty collection (e.g., Collections.emptyList()) instead of null. Callers can then safely call methods like list.size() without additional checks.

If the return type is not a collection, return a neutral “empty” object rather than null. This can be achieved with the Null Object pattern.

Example of the Null Object pattern:

public interface Action {
    void doSomething();
}

public interface Parser {
    Action findAction(String userInput);
}

Without the pattern, findAction might return null, leading to a null‑pointer when doSomething() is called.

public class MyParser implements Parser {
    private static final Action DO_NOTHING = new Action() {
        public void doSomething() { /* do nothing */ }
    };

    public Action findAction(String userInput) {
        // ...
        if (/* cannot find any actions */) {
            return DO_NOTHING;
        }
        // return actual action
    }
}

Comparison:

Redundant:

Parser parser = ParserFactory.getParser();
if (parser == null) {
    // handle error
}
Action action = parser.findAction(someInput);
if (action == null) {
    // do nothing
} else {
    action.doSomething();
}

Concise:

ParserFactory.getParser().findAction(someInput).doSomething();

Because the method never returns null, the caller can safely invoke doSomething() directly.

Additional tips:

When comparing strings, use the non‑null constant first: "bar".equals(foo) instead of foo.equals("bar").

Java 8 and Guava provide Optional to encapsulate potentially absent values, reducing explicit null checks.

If you consider returning null, think whether throwing an exception would be more appropriate.

design-patternsJavacode qualityAssertionsnull handling
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.