我想创建自己的DateTime验证注释
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalQuery;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
@Constraint(validatedBy = DateTimeValidator.class)
public @interface DateTime {
String message() default "{com.example.constraints.DateTime.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
TemporalQuery<?>[] queries() default {ZonedDateTime::from, LocalDateTime::from};
}
public class DateTimeValidator implements ConstraintValidator<DateTime, String> {
private DateTime dateTime;
private TemporalQuery<?>[] queries;
@Override
public void initialize(DateTime dateTime) {
queries = dateTime.queries();
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
try {
DateTimeFormatter.ISO_DATE_TIME.parseBest(s, queries);
} catch (DateTimeParseException e) {
return false;
}
return true;
}
}
是否有任何理由说明注释类型中不支持静态方法引用?否则,实现目标的最佳途径是什么?
答案 0 :(得分:1)
Java语言规范在普通接口和注释类型之间的JLS Chapter 9区分。
虽然普通接口允许标准的 MethodHeader 和 MethodBody 制作,但通过定义注释类型方法的限制性要大得多。具体而言,注释的值实现为虚拟方法,其return types are limited to:
因此,根据语言规范,如果您尝试使用任何其他类型,javac
必须生成编译时错误。这种语言限制的基本原理来自于注释值如何存储在字节码中所带来的实际限制。
在元素上放置注释时,元素的字节码必须引用值,而不需要访问任何其他类。具体来说,所有注释值实际上都存储在封闭类常量池中。
常量池用于许多目的,但它是一种相对简单的数据结构,并且不希望用它来编码复杂数据。通常条目是类名,方法名,方法签名等。注释参数在池中编码的当前方式建议方法句柄至少需要三(3)个这样的条目对于上述内容,不考虑这些方法是静态,虚拟,构造函数还是来自接口的复杂性。它们涉及仿制药吗?等
如上所述,其中一个允许的类型是任何枚举。如果您希望支持的TemporalQuery
实现可以在编译时限制为固定集 ,那么您可以定义enum
以包含每个受支持实现的静态成员并将其用作间接层:
public enum TemporalQueryValidation {
ZONED_DATE_TIME(ZoneDateTime::from),
LOCAL_DATE_TIME(LocalDateTime::from),
// ... more ...
;
private final TemporalQuery<?> query;
private TemporalQueryValidation (TemporalQuery<?> q) {
this.query = q;
}
TemporalQuery<?> getQuery() {
return query;
}
}
@Constraint(validatedBy = DateTimeValidator.class)
public @interface DateTime {
// ... other annotation values ...
TemporalQueryValidation[] queries() default { ZONED_DATE_TIME, LOCAL_DATE_TIME };
}
public class DateTimeValidator implements ConstraintValidator<DateTime, String> {
private DateTime dateTime;
private TemporalQuery<?>[] queries;
@Override
public void initialize(DateTime dateTime) {
TemporalQueryValidation[] validations = dateTime.queries();
queries = new TemporalQuery<?>[validations.length];
for (int i = 0; i < queries.length; i++) {
queries[i] = validations[i].getQuery();
}
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
try {
DateTimeFormatter.ISO_DATE_TIME.parseBest(s, queries);
} catch (DateTimeParseException e) {
return false;
}
return true;
}
}