Перейти к основному содержимому

Аннотации Spring Null-Safety

· 4 мин. чтения

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 , то увидим предупреждение:

./0fc9908d7525819eb6f530abb995d347.png

Благодаря этому указанию мы заранее знаем о проблеме и можем предпринять соответствующие действия, чтобы избежать сбоя во время выполнения.

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 , но видим аналогичную оговорку:

./6d62c86b84bda69d5d613a2bee10816a.png

Аннотация @NonNullFields делает наш код менее подробным, обеспечивая при этом тот же уровень безопасности, что и @NonNull .

4. Аннотация @Nullable

Аннотация @NonNullFields , как правило, предпочтительнее, чем @NonNull , поскольку она помогает сократить количество шаблонов. Иногда мы хотим исключить некоторые поля из ненулевого ограничения, указанного на уровне пакета.

Вернемся к полю nickName и украсим его аннотацией @Nullable :

@Nullable
private String nickName;

Предупреждение, которое мы видели раньше, теперь исчезло:

./ea947b3cf6e75846024e1df412efa9d4.png

В этой ситуации мы использовали аннотацию @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 :

./f7e087509b0ed8f45aeee9566633bba5.png

Обратите внимание, что, как и в случае с аннотацией @NonNullFields , мы можем переопределить @NonNullApi на уровне метода с помощью аннотации @Nullable .

6. Заключение

Spring null-safety — отличная функция, которая помогает уменьшить вероятность NPE. Однако есть два важных момента, о которых нам следует помнить при использовании этой функции:

  • Его можно использовать только в вспомогательном инструменте разработки, таком как IntelliJ IDEA.
  • Он не требует нулевых проверок во время выполнения — нам все еще нужно самим писать код, чтобы предотвратить NPE.

Исходный код этого руководства можно найти на GitHub .