Использование NotNull Annotation в аргументе метода
Я только начал использовать аннотацию @NotNull
с Java 8 и получить некоторые неожиданные результаты.
У меня есть такой метод:
public List<Found> findStuff(@NotNull List<Searching> searchingList) {
... code here ...
}
Я написал тест JUnit, передающий значение null для аргумента searchList. Я ожидал, что произойдет какая-то ошибка, но она прошла, как будто аннотации не было. Это ожидаемое поведение? Из того, что я понял, это должно было позволить вам пропустить код кода проверки работоспособности.
Было бы весьма полезно объяснить, что именно @NotNull должно делать.
Ответы
Ответ 1
@Nullable
и @NotNull
ничего не делают сами по себе. Предполагается, что они действуют как инструменты документирования.
Аннотация @Nullable
напоминает вам о необходимости ввести проверку NPE, когда:
- Вызов методов, которые могут вернуть ноль.
- Разыменование переменных (полей, локальных переменных, параметров), которые могут быть нулевыми.
@NotNull
Аннотация, на самом деле, является явным договором, в котором говорится следующее:
- Метод не должен возвращать ноль.
- Переменная (например, поля, локальные переменные и параметры) не может содержать нулевое значение.
Например, вместо того, чтобы писать:
/**
* @param aX should not be null
*/
public void setX(final Object aX ) {
// some code
}
Вы можете использовать:
public void setX(@NotNull final Object aX ) {
// some code
}
Кроме того, @NotNull
часто проверяется ConstraintValidators (например, spring и в спящем режиме).
Сама аннотация @NotNull
не выполняет никакой проверки, поскольку определение аннотации не предоставляет ссылки на тип ConstraintValidator
.
Для получения дополнительной информации см.:
- Проверка бина
- NotNull.java
- Constraint.java
- ConstraintValidator.java
Ответ 2
Как упомянуто выше @NotNull
ничего не делает само по себе. Хороший способ использования @NotNull
- использовать его с Objects.requireNonNull
public class Foo {
private final Bar bar;
public Foo(@NotNull Bar bar) {
this.bar = Objects.requireNonNull(bar, "bar must not be null");
}
}
Ответ 3
Чтобы сделать @NotNull
активным, вам нужен Lombok:
https://projectlombok.org/features/NonNull
import lombok.NonNull;
Следуйте: какую аннотацию @NotNull Java следует использовать?
Ответ 4
SO @NotNull просто является тегом... Если вы хотите его проверить, вы должны использовать что-то вроде hibernate validator jsr 303
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
Set<ConstraintViolation<List<Searching>> violations = validator.validate(searchingList);
Ответ 5
Если вы используете Spring, вы можете форсировать проверку, аннотируя класс с помощью @Validated
:
import org.springframework.validation.annotation.Validated;
Более подробная информация доступна здесь: проверка Javax @NotNull аннотации использования
Ответ 6
Чтобы проверить валидацию метода в тесте, вы должны заключить его в прокси в методе @Before.
@Before
public void setUp() {
this.classAutowiredWithFindStuffMethod = MethodValidationProxyFactory.createProxy(this.classAutowiredWithFindStuffMethod);
}
С MethodValidationProxyFactory как:
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
public class MethodValidationProxyFactory {
private static final StaticApplicationContext ctx = new StaticApplicationContext();
static {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
processor.afterPropertiesSet(); // init advisor
ctx.getBeanFactory()
.addBeanPostProcessor(processor);
}
@SuppressWarnings("unchecked")
public static <T> T createProxy(T instance) {
return (T) ctx.getAutowireCapableBeanFactory()
.applyBeanPostProcessorsAfterInitialization(instance, instance.getClass()
.getName());
}
}
А затем добавьте свой тест:
@Test
public void findingNullStuff() {
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> this.classAutowiredWithFindStuffMethod.findStuff(null));
}