1. Обзор
Начиная с Spring 5 у нас теперь есть доступ к интересной функции, помогающей нам писать более безопасный код. Эта функция называется нулевой безопасностью, группа аннотаций работает как защита, которая следит за потенциальными нулевыми ссылками.
Вместо того, чтобы позволить нам работать с небезопасным кодом, функция нулевой безопасности выдает предупреждения во время компиляции. Такие предупреждения могут предотвратить катастрофические исключения нулевого указателя (NPE) во время выполнения.
2. Аннотация @NonNull
Аннотация @NonNull является самой важной среди всех аннотаций функции защиты от нулей .
Мы можем использовать эту аннотацию, чтобы объявить ненулевое ограничение везде, где ожидается ссылка на объект: поле, параметр метода или возвращаемое значение метода.
Предположим, у нас есть класс с именем Person
:
public class Person {
private String fullName;
void setFullName(String fullName) {
if (fullName != null && fullName.isEmpty()) {
fullName = null;
}
this.fullName = fullName;
}
// getter
}
Это определение класса допустимо, но имеет недостаток — поле fullName
может иметь значение null
. Если это произойдет, мы можем получить NPE при работе с fullName
.
Функция нулевой безопасности Spring позволяет инструментам сообщать о такой опасности. Например, если мы напишем код в IntelliJ IDEA и украсим поле fullName аннотацией
@NonNull
, то увидим предупреждение:
Благодаря этому указанию мы заранее знаем о проблеме и можем предпринять соответствующие действия, чтобы избежать сбоя во время выполнения.
3. Аннотация @NonNullFields
Аннотация @NonNull
полезна для обеспечения нулевой безопасности. Однако мы бы загрязнили всю кодовую базу, если бы украсили все ненулевые поля этой аннотацией.
Мы можем избежать злоупотребления @NonNull
с помощью другой аннотации — @NonNullFields
. Эта аннотация применима на уровне пакета, уведомляя наши средства разработки о том, что все поля в аннотированном пакете по умолчанию не пусты.
Чтобы аннотация @NonNullFields срабатывала
, нам нужно создать файл с именем package-info.java
в корневом каталоге пакета и аннотировать пакет с помощью @NonNullFields
:
@NonNullFields
package org.foreach.nullibility;
Давайте объявим еще одно свойство в классе Person
с именем nickName
:
package org.foreach.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
}
На этот раз мы не украшаем поле nickName с помощью @NonNull
,
но видим аналогичную оговорку:
Аннотация @NonNullFields
делает наш код менее подробным, обеспечивая при этом тот же уровень безопасности, что и @NonNull
.
4. Аннотация @Nullable
Аннотация @NonNullFields
, как правило, предпочтительнее, чем @NonNull
, поскольку она помогает сократить количество шаблонов. Иногда мы хотим исключить некоторые поля из ненулевого ограничения, указанного на уровне пакета.
Вернемся к полю nickName
и украсим его аннотацией @Nullable
:
@Nullable
private String nickName;
Предупреждение, которое мы видели раньше, теперь исчезло:
В этой ситуации мы использовали аннотацию @Nullable
, чтобы переопределить семантику @NonNullFields
в поле.
5. Аннотация @NonNullApi
Аннотация @NonNullFields применяется только к полям
, как следует из ее названия. Если мы хотим иметь такое же влияние на параметры методов и возвращаемые значения, нам понадобится @NonNullApi
.
Как и в случае с @NonNullFields
, мы должны указать аннотацию @NonNullApi
в файле package-info.java
:
@NonNullApi
package org.foreach.nullibility;
Давайте определим геттер для поля nickName
:
package org.foreach.nullibility;
// import statements
public class Person {
@Nullable
private String nickName;
String getNickName() {
return nickName;
}
// other declarations
}
При действующей аннотации @NonNullApi
выдается предупреждение о возможном нулевом
значении, созданном методом getNickName
:
Обратите внимание, что, как и в случае с аннотацией @NonNullFields
, мы можем переопределить @NonNullApi
на уровне метода с помощью аннотации @Nullable
.
6. Заключение
Spring null-safety — отличная функция, которая помогает уменьшить вероятность NPE. Однако есть два важных момента, о которых нам следует помнить при использовании этой функции:
- Его можно использовать только в вспомогательном инструменте разработки, таком как IntelliJ IDEA.
- Он не требует
нулевых
проверок во время выполнения — нам все еще нужно самим писать код, чтобы предотвратить NPE.
Исходный код этого руководства можно найти на GitHub .