首先,我们需要知道什么是容器元素–其实就是List、Set、Map等。我们也知道,使用容器元素的时候,需要指定容器能容纳的数据的类型,例如,List<String>
就是说这个List容器可以容纳String类型,这里的String叫做参数化类型。本文要讲的就是对参数化类型约束。
需要注意的是,如果想要将一个约束应用到参数化类型上,那么这个约束的定义中的@Target中必须包含ElementType.TYPE_USE。什么意思呢?我们以validator-api标准的非空约束为例解释一下。从该约束的定义中我们可以看到它的@Target中包含了TYPE_USE这个值,由此,我们知道@NotNull约束可以被应用到参数化类型上。
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Repeatable(List.class)
@Documented
@Constraint(validatedBy = { })
public @interface NotNull {
String message() default "{javax.validation.constraints.NotNull.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
/**
* Defines several {@link NotNull} annotations on the same element.
*
* @see javax.validation.constraints.NotNull
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@interface List {
NotNull[] value();
}
}
截止Bean Validation 2.0,Bean Validation(JSR标准)内置的和Hibernate Validator(JSR标准的实现)特有的约束都指定了ElementType.TYPE_USE。所以,我们可以直接在参数化类型上使用这些约束。但是,如果想要在参数化类型上使用自定义的约束,一定记得将ElementType.TYPE_USE加到自定义的约束上。
内置的受支持的容器元素有这些:java.util.Iterable的实现(List、Set等)、java.util.Map的实现、java.util.Optional、java.util.OptionalInt、java.util.OptionalDouble、java.util.OptionalLong等。自定义的容器元素的约束本文不讲。
下面,我们以Set为例子来感性认识一下容器约束。
public class Car {
private Set<@NotNull String> parts = new HashSet<>();
public Set<String> getParts() {
return parts;
}
public void setParts(Set<String> parts) {
this.parts = parts;
}
}
@Test
public void setTest() {
Car car = new Car();
Set<String> parts = new HashSet<>();
parts.add("wheel");// 没问题
parts.add("");// 没问题
parts.add(null);// 有问题
car.setParts(parts);
Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car);
logger.info("违反的约束的个数:{}", constraintViolations.size());
for (ConstraintViolation<Car> constraintViolation : constraintViolations) {
logger.info("违反的约束:{}, {}", constraintViolation.getExecutableReturnValue(),
constraintViolation.getMessage());
}
}
INFO [main] com.qs.mmeng.hibernate.validator.constraints.container.ContainerElementConstraintTest.setTest : 违反的约束的个数:1
INFO [main] com.qs.mmeng.hibernate.validator.constraints.container.ContainerElementConstraintTest.setTest : 违反的约束:null, 不能为null
当然,这个例子非常简单,其他的容器元素也都是类似的。