繁体   English   中英

在方法参数中使用 NotNull Annotation

[英]Using NotNull Annotation in method argument

我刚开始在 Java 8 中使用@NotNull注释并得到一些意想不到的结果。

我有一个这样的方法:

public List<Found> findStuff(@NotNull List<Searching> searchingList) {
    ... code here ...
}

我编写了一个 JUnit 测试,传入参数 searchList 的空值。 我原以为会发生某种类型的错误,但结果好像注释不存在一样。 这是预期的行为吗? 据我了解,这是为了让您跳过编写样板空检查代码。

对@NotNull 究竟应该做什么的解释将不胜感激。

@Nullable@NotNull自己什么都不做。 它们应该充当文档工具。

@Nullable注释提醒您在以下情况下引入 NPE 检查的必要性:

  1. 调用可以返回 null 的方法。
  2. 取消引用可以为空的变量(字段、局部变量、参数)。

@NotNull Annotation 实际上是一个明确的契约,声明了以下内容:

  1. 方法不应返回 null。
  2. hold null value.变量(如字段,局部变量和参数)不可持有空值。

例如,而不是写:

/**
 * @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 和 hibernate 中)。

@NotNull注释本身不进行任何验证,因为注释定义不提供任何ConstraintValidator类型引用。

有关更多信息,请参阅:

  1. Bean验证
  2. 非空文件
  3. 约束.java
  4. 约束验证器.java

如上所述,@ @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");
    }
}

要使@NotNull处于活动状态,您需要 Lombok:

https://projectlombok.org/features/NonNull

import lombok.NonNull;

关注: 我应该使用哪个 @NotNull Java 注释?

所以@NotNull 只是一个标签......如果你想验证它,那么你必须使用类似 hibernate validator jsr 303 的东西

ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
 Set<ConstraintViolation<List<Searching>> violations = validator.validate(searchingList);

如果您使用的是 Spring,您可以通过使用@Validated注释类来强制验证:

import org.springframework.validation.annotation.Validated;

此处提供更多信息: Javax @NotNull 注释用法

你也可以使用@NonNullprojectlombok (lombok.NonNull)

我这样做是为了创建我自己的验证注释和验证器:

ValidCardType.java (放置在方法/字段上的注释)

@Constraint(validatedBy = {CardTypeValidator.class})
@Documented
@Target( { ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidCardType {
    String message() default "Incorrect card type, should be among: \"MasterCard\" | \"Visa\"";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

并且,触发检查的验证器: CardTypeValidator.java

public class CardTypeValidator implements ConstraintValidator<ValidCardType, String> {
    private static final String[] ALL_CARD_TYPES = {"MasterCard", "Visa"};

    @Override
    public void initialize(ValidCardType status) {
    }
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return (Arrays.asList(ALL_CARD_TYPES).contains(value));
    }
}

你可以做一些非常类似于检查@NotNull事情。

要在测试中测试您的方法验证,您必须将其包装在 @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));

}
I resolved it with

@JsonSetter(nulls = Nulls.AS_EMPTY)
@NotBlank
public String myString;

Request Json:
{
  myString=null
}
 Response:
 error must not be blank

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM