Spring Null-Safety Annotations – Spring的Null-安全注解

最后修改: 2018年 11月 6日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

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.

从Spring 5开始,我们现在可以使用一个有趣的功能来帮助我们编写更安全的代码。这个特性被称为null-safety,一组注解就像一个保障措施,它能注意到潜在的空引用。

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.

空值安全功能不是让我们逃避不安全的代码,而是在编译时产生警告。这种警告可以防止在运行时出现灾难性的空指针异常(NPE)。

2. The @NonNull Annotation

2.@NonNull 注释

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

@NonNull 注解是空安全特性的所有注释中最重要的。我们可以在任何预期有对象引用的地方使用该注解来声明非空约束:一个字段、一个方法参数或一个方法的返回值。

Suppose we have a class named Person:

假设我们有一个名为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.

这个类定义是有效的,但是有一个缺陷–fullName字段可能被设置为null。如果发生这种情况,我们在处理fullName时可能会出现NPE。

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:

Spring的null-safety特性使工具能够报告这种危险。例如,如果我们在IntelliJ IDEA中编写代码,并且用@NonNull注解来装饰fullName字段,我们会看到一个警告。

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

3.@NonNullFields 注释

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.

@NonNull 注解有助于保证空值的安全性。然而,如果用这个注解来装饰所有非空字段,我们会污染整个代码库。

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.

我们可以通过另一个注解来避免@NonNull的滥用,即@NonNullFields该注解适用于包级别,通知我们的开发工具,被注解的包中的所有字段默认为非空。

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-info.java的文件,并在包上注释@NonNullFields

@NonNullFields
package org.baeldung.nullibility;

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

让我们在Person类中声明另一个属性,叫做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:

这一次,我们没有用nickName字段点缀@NonNull,但仍然看到类似的注意事项。

nonnullfields annotation 3

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

@NonNullFields注解使我们的代码不那么冗长,同时确保了与@NonNull提供的安全水平相同。

4. The @Nullable Annotation

4.@Nullable 注释

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.

@NonNullFields注解通常比@NonNull更好,因为它有助于减少模板。有时,我们想让一些字段不受包级别上指定的非空值约束。

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

让我们回到nickName字段,用@Nullable注解来装饰它。

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

在这种情况下,我们使用@Nullable注解来覆盖@NonNullFields对字段的语义。

5. The @NonNullApi Annotation

5.@NonNullApi 注释

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.

@NonNullFields 注解只适用于,如其名称所示,字段。如果我们想对方法的参数和返回值产生同样的影响,我们将需要@NonNullApi

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

@NonNullFields一样,我们必须在@NonNullApi注释中指定package-info.java文件。

@NonNullApi
package org.baeldung.nullibility;

Let’s define a getter for the nickName field:

让我们为nickName字段定义一个getter。

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 possible null value produced by the getNickName method:

@NonNullApi注解生效的情况下,会对getNickName方法产生的可能的null值发出一个警告。

nonnullapi annotation

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

请注意,就像@NonNullFields注解一样,我们可以在方法级别用@Nullable注解覆盖@NonNullApi

6. Conclusion

6.结论

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:

Spring的null-safety是一个伟大的功能,它有助于减少NPE的可能性。然而,在使用这一特性时,我们需要注意两个重要的问题。

  • 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 over on GitHub.

本教程的源代码可以在GitHub上找到over