DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • From Database Changes to Real-Time Actions at Scale: Oracle GoldenGate and Java
  • How (and Why) to Build Dynamic Data Pipelines
  • Two AI Agents, One Database: Solving Concurrent Updates With Optimistic Locking
  • MySQL Instant DDL: Metadata Locks, Waiting Writers, and Query Pileups

Trending

  • Full-Text Search Meets the Graph: Apache Lucene Inside Neo4j
  • Kubernetes Rolling Updates Are Lying to You — and Your Users Are Paying for It
  • Introduction to Error Prone: How to Catch Bugs at Compile Time
  • Slopsquatting: Building a Scanner That Catches AI-Hallucinated Packages Before They Reach Production

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  1. DZone
  2. Data Engineering
  3. Databases
  4. 10 Tips to Handle Null Effectively

10 Tips to Handle Null Effectively

Nulls and the dreaded NPE can be awful, but by maintaining encapsulation, keeping your code simple, and using nulls only in certain situations, you can come out on top.

By 
Grzegorz Ziemoński
·
Jan. 26, 17 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
132.6K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

When I started programming in Java, I considered the null value my enemy and I dreaded NullPointerExceptions, which happened fairly often to me. Over time, I learned to work with it, and nowadays, I can consider my personal battle with nulls a victory. Most NPEs that I see nowadays are caused by incorrectly set up mocks during development. I can’t even remember the last time I caused an NPE in a production environment. But enough bragging, here’s my list of practices when dealing with null values.

1. Don’t Overcomplicate Things

Handling nulls can be a complicated problem on its own and therefore we should make it as clean and as obvious as possible. One very bad practice that I’ve seen in some codebases is using Objects methods, Optional classes, or even a separate method using Optional in places where a simple null check would be enough. This caused me to check where the method comes from, what it contains, and wonder what the difference is between this and direct comparison. Of course, your mileage may vary, but for me, this is significant overhead that we should avoid.

if (Optional.ofNullable(myVariable).isPresent()) // bad
if (Objects.nonNull(myVariable)) // better, but still bad
if (myVariable != null) // good


2. Use Objects Methods as Stream Predicates

Although Objects.isNull and Objects.nonNull are not the best fit for typical null checks, they are a perfect fit to use with streams. The filtering or matching lines with them read (arguably) much better than those with operators. In fact, this is the reason why they were introduced in the JDK.

myStream.filter(Objects::nonNull)
myStream.anyMatch(Objects::isNull)


3. Never Pass Null as an Argument

This is one of the most important principles of good coding, but if you don’t know it already, you deserve an explanation. Passing null to indicate that there’s no value for a given argument might seem like a viable option. But it has two big disadvantages:

  1. You need to read the function’s implementation and figure out if it, and potentially every affected function down the way, can handle null value correctly.
  2. You have to always be careful when changing function’s implementation not to throw away something that might handle nulls for its users. Otherwise, you have to search through the whole source code to check if null is being passed anywhere.

By accepting the principle of never passing null, both of these problems are gone forever. And what about a function with optional parameters? It’s simple, just overload the function with different sets of parameters:

void kill() {
    kill(self);
}

void kill(Person person) {
    person.setDeathTime(now());
}


By the way, since the two disadvantages are not that visible in the scope of a single class, you can give up on the rule when dealing with private methods. Just make sure things are safe from the outside.

4. Validate Public API Arguments

You and your team might use the principle of not passing nulls with great success, but when you’re exposing a public API, you have no control over its users and what they pass to your functions. For this reason, always check the arguments being passed to your public APIs for correctness. If your only concern is the nullity of the argument, consider using the requireNonNull function from the Objects class:

public Foo(Bar bar, Baz baz) {
    this.bar = Objects.requireNonNull(bar, "bar must not be null");
    this.baz = Objects.requireNonNull(baz, "baz must not be null");
}


5. Leverage Optional

Before Java 8, it was common that a method would return null in the case of a missing value. This was inherently error prone, as the developer had to always check the documentation or, if the documentation was missing, the underlying source code for the possiblity of null being returned. Since JDK 8 was released, we have the Optional class available, designed specifically to indicate that a return value might be missing. A developer calling a method with Optional as the return value has to explicitly handle the case when the value is not present. Therefore, wrap your return types with Optional when applicable.

Optional<String> makingYouCheck() {
    // stuff
}

makingYouCheck().orElseThrow(ScrewYouException::new);


6. Return Empty Collections Instead of Null

We already know that null is not the best return value for a method and that we can make use of the Optional class to indicate that the value might be missing. But things are a bit different when we’re talking about collections. Since a collection can contain any amount of elements, it can also contain… 0 elements! There are even special emptyXxx methods in the Collections class that return such collections. Therefore, we should avoid returning null or complicating things with Optional and return an empty collection when there are no values to fill it with.

List<String> findSomething() {
    if (someCondition) {
        return Collections.emptyList();
    }
    // stuff
}


7. Optional Ain’t for Fields

As I already said, Optional was designed to indicate missing return values. One tempting case that it was not designed for and surely is not necessary for is class fields. By means of encapsulation, you should have full control over the field's value, including null. On the other hand, making fields explicitly Optional might bring you weird problems like:

  • How should you write a constructor or setter for such a field?
  • You have to deal with the Optional even in cases when you’re sure that the value is there.
  • How should automappers handle those fields?

Therefore, use direct references for fields and carefully analyze whether a field can be null or not at any given point. If your class is well-encapsulated, this should be fairly easy.

8. Use Exceptions Over Nulls

One strange case when you might see people using null is exceptional situations. This is an inherently error prone practice, as critical errors can be omitted or resurface in different places of the system, causing debugging to be a pain. Therefore, always throw an exception instead of returning null if something went wrong.

9. Test Your Code

Well, this advice is related to all kinds of bugs, not just unexpected nulls, but it’s so important that I felt it should make it to the list. Testing your code thoroughly using an environment similar to production is a great way to prevent NPEs. Never release a piece of code without making sure it works. There’s no such thing as “a quick, simple fix that doesn’t require testing.”

10. Double Check

Every time you assume that some reference cannot be null, double check that you’re right. This is especially important when dealing with huge legacy databases or external providers. With the former, take the time to check if the columns you’re meaning to use do not contain any null values, and if they do, check if those rows can make it into your system. In case of external providers, rely on contracts, documentation, and if you’re not sure, send an email or call someone to make sure your assumptions are right. This might be annoying, especially when working with a poorly documented API, but when it comes to nulls: better safe than sorry!

Database

Published at DZone with permission of Grzegorz Ziemoński. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • From Database Changes to Real-Time Actions at Scale: Oracle GoldenGate and Java
  • How (and Why) to Build Dynamic Data Pipelines
  • Two AI Agents, One Database: Solving Concurrent Updates With Optimistic Locking
  • MySQL Instant DDL: Metadata Locks, Waiting Writers, and Query Pileups

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook