Using NullAway to Avoid NullPointerExceptions – 使用NullAway来避免NullPointerExceptions

最后修改: 2020年 3月 11日

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

1. Overview

1.概述

We’ve been undertaking numerous strategies over the years, from Elvis operators to Optional, to help remove NullPointerExceptions from our apps. In this tutorial, we’ll learn about Uber’s contribution to the conversation, NullAway, and how to use it.

多年来,我们一直在采取众多策略,从猫王运营商到Optional,以帮助从我们的应用程序中移除NullPointerExceptions。在本教程中,我们将了解Uber对对话的贡献,NullAway,以及如何使用它。

NullAway is a build tool that helps us to eliminate NullPointerExceptions (NPEs) in our Java code.

NullAway是一个构建工具,可以帮助我们消除Java代码中的NullPointerExceptions(NPEs)。

This tool performs a series of type-based, local checks to ensure that any pointer that gets dereferenced in your code cannot be null. It has low build-time overhead and can be configured to run in every build of your code.

这个工具执行了一系列基于类型的本地检查,以确保在你的代码中被解引用的任何指针不能是null。它的构建时间开销很低,可以被配置为在你的代码的每次构建中运行。

2. Installation

2.安装

Let’s take a look at how to install NullAway and its dependencies. In this example, we’re going to configure NullAway using Gradle.

让我们来看看如何安装NullAway及其依赖项。在这个例子中,我们将使用Gradle来配置NullAway。

NullAway is dependant on Error Prone. Therefore, we will add the errorprone plugin:

NullAway依赖于Error Prone>。因此,我们将添加errorprone插件。

plugins {
  id "net.ltgt.errorprone" version "1.1.1"
}

We’ll also add four dependencies in different scopes: annotationProcessor, compileOnly, errorprone, and errorproneJavac:

我们还将在不同范围内添加四个依赖项。annotationProcessorcompileOnlyerrorproneerrorproneJavac

dependencies {
  annotationProcessor "com.uber.nullaway:nullaway:0.7.9"
  compileOnly "com.google.code.findbugs:jsr305:3.0.2"
  errorprone "com.google.errorprone:error_prone_core:2.3.4"
  errorproneJavac "com.google.errorprone:javac:9+181-r4173-1"
}

Finally, we’ll add the Gradle task that configures how NullAway works during the compilation:

最后,我们将添加Gradle任务,配置NullAway在编译过程中的工作方式。

import net.ltgt.gradle.errorprone.CheckSeverity

tasks.withType(JavaCompile) {
    options.errorprone {
        check("NullAway", CheckSeverity.ERROR)
        option("NullAway:AnnotatedPackages", "com.baeldung")
    }
}

The above task sets NullAway severity to the error level which means we can configure NullAway to stop the build with an error. By default, NullAway will just warn the user at compile time.

上述任务将NullAway的严重性设置为错误级别,这意味着我们可以配置NullAway在出现错误时停止构建。默认情况下,NullAway只是在编译时警告用户。

Additionally, the task sets the package to be checked for null dereferences.

此外,该任务还设置了要检查的包,以防止出现空解。

And that’s it, we’re ready now to use the tool in our Java code.

就这样,我们现在已经准备好在我们的Java代码中使用这个工具了。

Similarly, we can use other build systems, Maven or Bazel, to integrate the tool.

同样,我们可以使用其他构建系统、Maven或Bazel,来集成工具。

3. Usage

3.使用方法

Let’s say we have a Person class, containing an age attribute. Additionally, we have a getAge method that takes a Person instance as a parameter:

假设我们有一个Person类,包含一个age属性。此外,我们有一个getAge方法,它需要一个Person实例作为参数。

Integer getAge(Person person) {
    return person.getAge();
}

At this point, we can see that getAge will throw a NullPointerException if person is null.

在这一点上,我们可以看到getAge将抛出一个NullPointerException,如果personnull

NullAway assumes every method parameter, return value, and field are non-null. Therefore, it will expect the person instance to be non-null.

NullAway假设每个方法的参数、返回值和字段都是非空的。因此,它将期望person实例为非

And let’s also say that there is someplace in our code that is, indeed, passing a null reference into getAge:

我们还可以说,在我们的代码中的某个地方,确实在向getAge传递一个空引用。

Integer yearsToRetirement() {
    Person p = null;
    // ... p never gets set correctly...
    return 65 - getAge(p);
}

Then, running a build will produce the following error:

然后,运行构建将产生以下错误。

error: [NullAway] passing @Nullable parameter 'null' where @NonNull is required
    getAge(p);

We can fix this error by adding a @Nullable annotation to our parameter:

我们可以通过给我们的参数添加一个@Nullable注解来解决这个错误。

Integer getAge(@Nullable Person person) { 
    // ... same as earlier
}

Now when we run a build, we’ll see a new error:

现在当我们运行构建时,我们会看到一个新的错误。

error: [NullAway] dereferenced expression person is @Nullable
    return person.getAge();
            ^

This is telling us that the person instance has the possibility of being null. We can fix this adding a standard null check:

这告诉我们,person实例有可能是null。我们可以通过添加一个标准的null检查来解决这个问题。

Integer getAge(@Nullable Person person) {
    if (person != null) {
        return person.getAge();
    } else {
        return 0;
    }
}

4. Conclusions

4.结论

In this tutorial, we’ve looked at how we can use NullAway to limit the possibilities of encountering NullPointerExceptions.

在本教程中,我们研究了如何使用NullAway来限制遇到NullPointerException的可能性。

As always all source code is available on GitHub.

一如既往,所有的源代码都可以在GitHub上获得