我刚刚开始在Java 8中使用@ notull注释,并得到了一些意想不到的结果。
我有一个这样的方法:
public List<Found> findStuff(@NotNull List<Searching> searchingList) {
... code here ...
}
我写了一个JUnit测试,传入参数searchingList的空值。我期望发生某种类型的错误,但它通过,就好像注释不存在一样。这是预期的行为吗?根据我的理解,这是为了允许您跳过编写样板空检查代码。
关于@NotNull到底应该做什么的解释将非常感激。
@Nullable和@NotNull本身不做任何事情。它们应该充当文档工具。
@Nullable Annotation提醒你在以下情况下引入NPE检查的必要性:
调用可以返回null的方法。
取消可以为空的变量(字段、局部变量、参数)的引用。
@NotNull注释实际上是一个明确的契约,声明如下:
方法不应该返回null。
变量(如字段、局部变量和参数)不能保持空值。
例如,不要写:
/**
* @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检查。在春天和冬眠)。
@ nottnull注释本身不做任何验证,因为注释定义没有提供任何ConstraintValidator类型引用。
更多信息见:
Bean验证
NotNull.java
Constraint.java
ConstraintValidator.java
要在测试中测试方法验证,必须在@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));
}
我这样做是为了创建自己的验证注释和验证器:
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。