How to Stop Checking for null in Java and Stay Sane

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

The Curse of null: Why Do We Write the Same Thing Over and Over?

\n\n

If you've been writing Java for more than a week, you've certainly encountered NullPointerException. And, most likely, your first reaction was: "Aha, I just need to check!". This is how miles of code like this are born:

\n\n
if (user != null) {\n    if (user.getAddress() != null) {\n        String city = user.getAddress().getCity();\n        if (city != null) {\n            System.out.println(city.toUpperCase());\n        }\n    }\n}\n
\n\n

This code works. But it's ugly. It turns reading logic into torture, and maintenance into a nightmare. The question "How do I avoid checking for nulls in Java?" on Stack Overflow has gathered thousands of views for a reason. Every Java developer asks it sooner or later.

\n\n

The good news: avoiding null checks is not only possible but necessary. Java is not JavaScript, and we have tools to write clean, safe code without "defensive" constructs. Let's break them all down — from the essential toolkit to advanced techniques.

\n\n

1. Optional<T> — Your Main Ally

\n\n

Since Java 8, we have Optional. It's a container that can hold a value or be empty. It was literally created to avoid null checks and make code more declarative.

\n\n

How does it work?

\n\n

Instead of returning null from a method, return Optional. And instead of checks, use method chains.

\n\n
// Bad\npublic String getCity(User user) {\n    if (user == null) return "Unknown";\n    Address address = user.getAddress();\n    if (address == null) return "Unknown";\n    return address.getCity();\n}\n\n// Good\npublic Optional<String> getCity(User user) {\n    return Optional.ofNullable(user)\n            .map(User::getAddress)\n            .map(Address::getCity);\n}\n\n// Usage\nString city = getCity(someUser).orElse("Unknown");\n
\n\n

Notice: not a single if. map only works if the value is not null. If null is encountered at any stage, the chain is interrupted, and you get Optional.empty().

\n\n

Popular Optional Methods

\n\n
    \n
  • orElse(T other) — return the value or a fallback
  • \n
  • orElseGet(Supplier<? extends T> other) — lazy version, computed only if needed
  • \n
  • orElseThrow(Supplier<? extends X> exceptionSupplier) — throw your own exception
  • \n
  • ifPresent(Consumer<? super T> consumer) — perform an action if the value is present
  • \n
  • filter(Predicate<? super T> predicate) — filter by a condition
  • \n
\n\n
// Example with filter\nOptional<String> name = Optional.of("Java");\nname.filter(n -> n.startsWith("J"))\n    .ifPresent(System.out::println); // Prints "Java"\n
\n\n

Important: Optional is intended for return values, not for class fields or method parameters. Don't overuse it.

\n\n

2. Objects.requireNonNull() — Utility for Explicit Contracts

\n\n

Sometimes null is an error, and it needs to be detected as early as possible. Instead of writing checks manually, use java.util.Objects.requireNonNull().

\n\n
public class UserService {\n    private final UserRepository repository;\n\n    public UserService(UserRepository repository) {\n        this.repository = Objects.requireNonNull(repository, \n            "UserRepository must not be null");\n    }\n\n    public User findById(Long id) {\n        Objects.requireNonNull(id, "ID must not be null");\n        return repository.findById(id);\n    }\n}\n
\n\n

This approach is called

Blogs

Book Recommendations