1. Overview

Starting with Spring 5, we now have access to an interesting feature helping us write safer code. This feature is called null safety, a group of annotations working like a safeguard that watches out for potential null references.

Rather than letting us get away with unsafe code, the null-safety feature produces warnings at compile time. Such warnings may prevent catastrophic null pointer exceptions (NPEs) at runtime.

2. The @NonNull Annotation

The @NonNull annotation is the most important among all the annotations of the null-safety feature. We can use this annotation to declare non-null constraint anywhere an object reference is expected: a field, a method parameter or a method’s return value.

Suppose we have a class named Person:

public class Person {
    private String fullName;

    void setFullName(String fullName) {
        if (fullName != null && fullName.isEmpty()) {
            fullName = null;
        }
        this.fullName = fullName;
    }

    // getter
}

This class definition is valid but has a defect – the fullName field may be set to null. If this happens, we could end up with an NPE when working with fullName.

The Spring null-safety feature enables tools to report such a danger. For instance, if we write code in IntelliJ IDEA and decorate the fullName field with the @NonNull annotation, we’ll see a warning:

nonnul annotation

Thanks to this indication, we’re aware of the problem in advance and able to take appropriate action to avoid a runtime failure.

3. The @NonNullFields Annotation

The @NonNull annotation is helpful in guaranteeing null safety. However, we would pollute the whole code base if adorning all non-null fields with this annotation.

We can avoid the abuse of @NonNull with another annotation – @NonNullFields. This annotation is applicable at the package level, notifying our development tools that all fields in the annotated package are, by default, non-null.

For the @NonNullFields annotation to kick in, we need to create a file named package-info.java in the root directory of the package and annotate the package with @NonNullFields:

@NonNullFields
package org.baeldung.nullibility;

Let’s declare another property in the Person class called nickName:

package org.baeldung.nullibility;

// import statements

public class Person {
    private String nickName;

    void setNickName(@Nullable String nickName) {
        if (nickName != null && nickName.isEmpty()) {
            nickName = null;
        }
        this.nickName = nickName;
    }

    // other declarations
}

This time, we don’t embellish the nickName field with @NonNull but still see a similar caveat:

nonnullfields annotation 3

The @NonNullFields annotation makes our code less verbose while ensuring the same level of safety that @NonNull provides.

4. The @Nullable Annotation

The @NonNullFields annotation is generally preferable to @NonNull as it helps reduce boilerplate. At times we want to exempt some fields from the non-null constraint specified at the package level.

Let’s go back to the nickName field and decorate it with the @Nullable annotation:

@Nullable
private String nickName;

The warning we saw before is gone now:

nullable annotation

In this situation, we used the @Nullable annotation to override the semantics of @NonNullFields on a field.

5. The @NonNullApi Annotation

The @NonNullFields annotation only applies to, as its name suggests, fields. If we want to have the same impact on the methods’ parameters and return values, we’ll need @NonNullApi.

As with @NonNullFields, we must specify the @NonNullApi annotation in the package-info.java file:

@NonNullApi
package org.baeldung.nullibility;

Let’s define a getter for the nickName field:

package org.baeldung.nullibility;

// import statements

public class Person {
    @Nullable
    private String nickName;

    String getNickName() {
        return nickName;
    }

    // other declarations
}

With the @NonNullApi annotation in effect, a warning is issued about a possibly null value produced by the getNickName method:

nonnullapi annotation

Notice that just like the @NonNullFields annotation, we can override the @NonNullApi at the method level with the @Nullable annotation.

6. Conclusion

Spring null safety is a great feature that helps diminish the possibility of NPEs. However, there are two important points we need to beware of while using this feature:

  • It’s only usable in a supporting development tool, such as IntelliJ IDEA
  • It doesn’t enforce null checks at runtime – we still need to write code ourselves to avert NPEs

The source code for this tutorial can be found on GitHub.