Java 为什么注释成员中不支持静态方法引用类型?

Java 为什么注释成员中不支持静态方法引用类型?,java,annotations,Java,Annotations,我想创建自己的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.Constrain

我想创建自己的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;
    }
}
导入java.time.format.DateTimeFormatter;
导入java.time.format.DateTimeParseException;
导入java.time.LocalDateTime;
导入java.time.ZonedDateTime;
导入java.time.temporal.TemporalQuery;
导入javax.validation.ConstraintValidator;
导入javax.validation.ConstraintValidatorContext;
@约束(validatedBy=DateTimeValidator.class)
公共@接口日期时间{
String message()默认值“{com.example.constraints.DateTime.message}”;
类[]组()默认值{};
类[]查询()默认值{ZonedDateTime::from,LocalDateTime::from};
}
公共类DateTimeValidator实现ConstraintValidator{
私有日期时间;
私有临时查询[]查询;
@凌驾
公共无效初始化(日期时间日期时间){
querys=dateTime.querys();
}
@凌驾
公共布尔值有效(字符串s、ConstraintValidatorContext ConstraintValidatorContext){
试一试{
DateTimeFormatter.ISO_DATE_TIME.parseBest(s,查询);
}捕获(DateTimeParse异常){
返回false;
}
返回true;
}
}
注释类型中不支持静态方法引用有什么原因吗?否则,实现我的目标的最佳方式是什么?

简而言之,因为语言禁止这样做。 Java语言规范区分了普通接口和注释类型

虽然普通接口允许标准MethodHeader和MethodBody生成,但注释类型方法的限制性要大得多。具体而言,注释的值实现为虚拟方法,其:

  • 原语
  • 阶级
  • 枚举类型
  • 其他注释(自身或允许循环路径返回自身的注释除外)
  • 上面的数组
因此,根据语言规范,
javac
必须在尝试使用任何其他类型时生成编译时错误。这种语言限制的基本原理来自于注释值如何存储在字节码中所施加的实际限制

在元素上放置注释时,元素的字节码必须引用值,而不需要访问任何其他类。具体来说,所有注释值实际上都存储在封闭类常量池中

常量池有很多用途,但它是一个相对简单的数据结构,不希望使用它来编码复杂的数据。通常条目是类名、方法名、方法签名等。池中注释参数的当前编码方式表明,方法句柄至少需要三(3)个上述条目,而不考虑这些方法是否为静态、虚拟、构造函数的复杂性,或者从一个接口。它们涉及仿制药吗?等等

你能做什么 如上所述,允许的类型之一是any Enum。如果希望支持的
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;
    }
}
公共枚举临时查询验证{
分区日期时间(ZoneDateTime::from),
本地日期时间(LocalDateTime::from),
//……更多。。。
;
私有最终临时查询;
专用临时查询验证(临时查询q){
this.query=q;
}
临时查询getQuery(){
返回查询;
}
}
@约束(validatedBy=DateTimeValidator.class)
公共@接口日期时间{
//…其他注释值。。。
TemporalQueryValidation[]queries()默认值{ZONED_DATE_TIME,LOCAL_DATE_TIME};
}
公共类DateTimeValidator实现ConstraintValidator{
私有日期时间;
私有临时查询[]查询;
@凌驾
公共无效初始化(日期时间日期时间){
TemporalQueryValidation[]validations=dateTime.queries();
查询=新的临时查询[validations.length];
for(int i=0;i