1. Обзор
На протяжении многих лет мы применяли множество стратегий, от операторов Элвиса до Optional
, чтобы помочь удалить исключения NullPointerException
из наших приложений. В этом руководстве мы узнаем о вкладе Uber в разговор, NullAway и о том, как его использовать.
NullAway — это инструмент сборки, который помогает нам устранять исключения NullPointerException
(NPE) в нашем коде Java.
Этот инструмент выполняет ряд локальных проверок на основе типов, чтобы гарантировать, что любой указатель, который разыменовывается в вашем коде, не может быть нулевым
. Он имеет низкие накладные расходы во время сборки и может быть настроен для запуска в каждой сборке вашего кода.
2. Установка
Давайте посмотрим, как установить NullAway и его зависимости. В этом примере мы собираемся настроить NullAway с помощью Gradle.
NullAway зависит от Error Prone . Поэтому мы добавим ошибочный
плагин:
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", "com.foreach")
}
}
Вышеупомянутая задача устанавливает серьезность NullAway на уровень ошибки, что означает, что мы можем настроить NullAway для остановки сборки с ошибкой. По умолчанию NullAway просто предупреждает пользователя во время компиляции.
Кроме того, задача задает проверку пакета на наличие нулевых разыменований.
Вот и все, теперь мы готовы использовать этот инструмент в нашем Java-коде.
Точно так же мы можем использовать другие системы сборки , Maven или Bazel ,
для интеграции инструмента.
3. Использование
Допустим, у нас есть класс Person
, содержащий атрибут возраста .
Кроме того, у нас есть метод getAge
, который принимает экземпляр Person
в качестве параметра:
Integer getAge(Person person) {
return person.getAge();
}
На данный момент мы видим, что getAge
вызовет исключение NullPointerException
, если person
имеет значение null
.
NullAway предполагает, что каждый параметр метода, возвращаемое значение и поле не являются нулевыми.
Следовательно, он будет ожидать, что экземпляр person
будет ненулевым
.
И давайте также скажем, что в нашем коде есть место, которое действительно передает нулевую ссылку в 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 может быть
нулевым
. Мы можем исправить это, добавив стандартную нулевую проверку:
Integer getAge(@Nullable Person person) {
if (person != null) {
return person.getAge();
} else {
return 0;
}
}
4. Выводы
В этом руководстве мы рассмотрели, как можно использовать NullAway, чтобы ограничить вероятность возникновения исключений NullPointerException
.
Как всегда весь исходный код доступен на GitHub .