Heart containing Coding Chica Java 101

It’s Pointers, Dear Watson! Java’s null

TIP: References Quick List

Table of Contents

  1. Table of Contents
  2. Introduction
  3. Java Primitives
  4. Java Objects
  5. The Meaning of null
  6. Null Pointer Exceptions
  7. Safe Guards for null Values
  8. Throwing A NullPointerException
  9. NullPointerExceptions Thrown by Java
  10. Summary

Introduction

When we create new Objects, Java may be able to figure out what size they currently require, but that could change throughout the life of the Object. If we were to store all of our data for our applications right next to all of the other data, then these changes could cause a problem as the data for our Objects changes (grows and shrinks) over time. Imagine if we changed one variable value, such as a name and had to shift all of the data in memory for the rest of our application to accommodate the change? Then, what if that isn’t the only Java application currently running? We could significantly slow down our applications with just a small adjustment! Thankfully, that isn’t how Java is setup.

Java Primitives

When we define a primitive value, such as an int, Java knows just how much room that variable will require. No matter what int value we store in that variable, or how many times we change it, it will still take up the same amount of memory.

Java Objects

However, when we create objects, we can nest objects in other objects and we can change values in any of those objects. How then, can Java keep track of all of the different values, if their size needs in memory keeps changing?

Let’s pretend that we have created a class to represent a spoon and use Lombok-generated getters and setters:

@AllArgConstructor
public class Spoon {
    @Getter
    @Setter
    private String brand = null;
    
    @Getter
    @Setter
    private boolean layingFlat = true;
    
    @Getter
    @Setter
    private boolean full = false;
    
    @Getter
    @Setter
    private boolean clean = false;
}

Let’s say that we create a Spoon object and then later discover a typo in the brand field for one of our Spoon objects. How does Java handle this sort of change? Our brand field is a String, which is an Object. Therefore, the variable doesn’t actually store the name value. Instead, it stores a pointer (imagine it like a location in a scavenger hunt). Once you get to that address, you can see what is inside.

Now, all Java has to store with the rest of the program is the pointer with the address. The actual Object is somewhere else. It can grow and shrink and the application doesn’t really care.

The Meaning of null

In Java, the value null means that there is no memory address to point to, as we do not have an object to look at. There is no treasure at the end of that scavenger hunt. Therefore, you cannot call methods, look at, or change field values when there is nothing there.

This could be an initial state, meaning that what we eventually want to store there isn’t yet ready. Or it could be a place holder value, such as if you ask a method to return the next value from an empty collection of objects.

When you try to access methods or fields within a null object reference, Java throws a NullPointerException.

Null Pointer Exceptions

If your application throws a NullPointerException, it either means:

  • Some code tried to use a object’s methods/fields without checking if the variable is null first, or
  • Some method was invoked that doesn’t allow a value to be null, and threw the NullPointerException to tell the calling code that it is doing something wrong.

Either way, there is a problem in the code. We may not have set things up the way we thought, or we may have forgotten some edge cases and need to add some safety checks.

Safe Guards for null Values

The guard rails for protecting against a NullPointerException is very simple, just put a “not equal to null” check in your code before you use any of an Object’s methods or fields:

if (myVariableNameHere != null) {
   // In this block, I can safely use the object's methods and fields.
}

Throwing A NullPointerException

Whenever we need to throw a NullPointerException in our code, we should always include a message about what variable was null. If it is right before your assignment is due or you are called out by your work in the middle of the night because an error is happening in production, then you want as good a sign-post as you can make for how to quickly solve the problem. If there is a NullPointerException that your code threw on purpose, then there should be a helpful message saying what variable had the problem.

if (myVariableNameHere == null) {
    throw new NullPointerException(“myVariableNameHere must not be null”);
}

It doesn’t need to be fancy. Just replace myVariableNameHere in the snippet above and the logs will help you quickly find the issue.

NullPointerExceptions Thrown by Java

If Java throws the NullPointerException, the amount of help you get in the error message will vary by the Java version and possibly the compiler (JDK) vendor you choose. Earlier Java behavior, didn’t include any message when a NullPointerException was thrown. If there were multiple objects in a given line of code that could be null, you had to figure out which was causing the issue.

More recently, I have been seeing situations where newer versions of Java are including a message to help identify which variable was null. However, I still prefer explicitly calling out the behavior in the code. This is two-fold:

  • Calling out the behavior in my code that I expect when a value is null gives me a chance to think it through and write a test case for that scenario.
  • By calling out the behavior I expect within the code itself, the code is less likely to be tightly coupled to (dependent upon) the compiler’s vendor or version.
    • The compiler is something provided by the server or local machine running the build. If different developers install slightly different versions or use different vendors when they setup their local machines and it changes the behavior of the application, then tests could become brittle and difficult to troubleshoot.

Summary

A null value in Java means that there is no address provided to find an object. There is no clue for your scavenger hunt. We should either check to see if objects are null before we use their methods or fields, or we should explicitly check (and add unit tests to confirm the behavior) for when an object is null. If a NullPointerException is thrown, it should have a helpful message and should come from our code, rather than the compiler, so our code’s behavior does not change unexpectedly from server-to-server as the compiler version and/or vendor varies.

It’s Pointers, Dear Watson! Java’s null

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.