Fundamentals 7 min read

Avoiding Excessive Null Checks in Java: Assertions, Exceptions, and the Null Object Pattern

The article explains why Java developers often litter code with null‑checks, distinguishes when null is a valid response versus an error, and proposes using assertions, exceptions, empty collections, or the Null Object pattern to write cleaner, safer code.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Avoiding Excessive Null Checks in Java: Assertions, Exceptions, and the Null Object Pattern

In Java it is common to see defensive null‑checks such as if (someObject != null) { someObject.doCalc(); } , which quickly pollutes the codebase with repetitive boilerplate.

This habit stems from methods that return null and a mindset that every return value must be verified, leading developers to over‑use null‑checks.

Two situations should be distinguished: (1) null is a meaningful, contract‑defined response, and (2) null indicates an invalid or erroneous situation.

When null is invalid (case 2), the preferred approaches are to use an assert with a helpful message or to throw a NullPointerException (or a custom exception), thereby failing fast and informing the caller.

When null is a valid “empty” result (case 1), return an empty collection (e.g., Collections.emptyList() ) instead of null , allowing callers to operate on the result without additional checks.

If the return type is not a collection, return a deliberately empty object rather than null . The article illustrates this with interfaces Action and Parser , where findAction might return null and cause a NullPointerException.

Applying the Null Object pattern, a static DO_NOTHING implementation of Action is provided, and findAction returns this object when no real action is found, guaranteeing a non‑null result.

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

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

With this pattern, client code can be simplified from verbose null‑checking:

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

to a concise chain:

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

Additional recommendations include using "bar".equals(foo) to avoid NPEs, leveraging Optional (Java 8/Guava) for better null handling, and considering throwing exceptions instead of returning null where appropriate.

JavaException HandlingBest PracticesAssertionsnull-checkNull Object pattern
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

login 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.