使用NullAway避免NullPointerException

2025/03/25

1. 概述

多年来,我们一直在采取多种策略,从Elvis运算符到Optional,以帮助从我们的应用程序中删除NullPointerException。在本教程中,我们将了解Uber对该领域的贡献NullAway以及如何使用它。

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

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

2. 安装

我们来看看如何安装NullAway及其依赖,在此示例中,我们将使用Gradle配置NullAway。

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

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

我们还将在不同范围内添加四个依赖:annotationProcessor、compileOnly、errorprone和errorproneJavac:

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"
}

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

import net.ltgt.gradle.errorprone.CheckSeverity

tasks.withType(JavaCompile) {
    options.errorprone {
        check("NullAway", CheckSeverity.ERROR)
        option("NullAway:AnnotatedPackages", "cn.tuyucheng.taketoday")
    }
}

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

此外,该任务还设置要检查的包是否存在空引用。

就这样,我们现在就可以在Java代码中使用该工具了。

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

3. 用法

假设我们有一个包含age属性的Person类,此外,我们还有一个将Person实例作为参数的getAge方法:

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

此时,我们可以看到如果person为null getAge将抛出NullPointerException。

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

并且假设我们的代码中确实有某个地方将空引用传递给了getAge:

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

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

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

我们可以通过在参数中添加@Nullable注解来修复此错误:

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

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

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

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

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

4. 总结

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

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章