Java 将子类型中类型参数的注释链接到超类型中声明的类型参数

Java 将子类型中类型参数的注释链接到超类型中声明的类型参数,java,generics,reflection,annotations,java-8,Java,Generics,Reflection,Annotations,Java 8,让有一个类型扩展java.util.Map: public interface IdentifiableMap<ID, KEY, VALUE> extends Map<KEY, VALUE>{ ID getId(); } 公共接口可识别映射扩展映射{ ID getId(); } 还有一个该类型的字段,它在其中一个类型参数上声明注释(在Java 8中是可能的): private identiablemap myMap=。。。; 使用Java reflecti

让有一个类型扩展
java.util.Map

public interface IdentifiableMap<ID, KEY, VALUE> extends Map<KEY, VALUE>{

    ID getId();
}
公共接口可识别映射扩展映射{
ID getId();
}
还有一个该类型的字段,它在其中一个类型参数上声明注释(在Java 8中是可能的):

private identiablemap myMap=。。。;
使用Java reflection API,我如何从这个声明中找出为
Map
接口的类型参数提供了哪些注释?换句话说,我想推断,
java.util.Map
K
类型参数已经给出了
@Size
注释


我知道如何从字段的
AnnotatedParameterizedType
中获取类型参数的注释,但我不知道如何将其与超级类型
映射的类型参数关联,不幸的是,这远不是件容易的事。下面的代码假设您要查找直接实现或扩展该类型的类型的注释,否则代码将变得更加复杂,或者间接实现多次的接口会出现歧义问题

static Annotation[][] getActualAnnotations(AnnotatedType at, Class<?> target) {
    Type[] typeParameters = target.getTypeParameters();
    if(typeParameters.length==0) return new Annotation[0][];
    Type t=at.getType();
    Map<Type,Annotation[]> atArgAnnos;
    Class<?> raw;
    if(t instanceof Class) {
        atArgAnnos=Collections.emptyMap();
        raw=(Class<?>)t;
        if(raw==target) return new Annotation[typeParameters.length][0];
    }
    else if(t instanceof ParameterizedType) {
        ParameterizedType pt=(ParameterizedType)t;
        raw=(Class<?>)pt.getRawType();
        Type[] param=raw.getTypeParameters();
        Annotation[][] a = Arrays
            .stream(((AnnotatedParameterizedType)at).getAnnotatedActualTypeArguments())
            .map(AnnotatedType::getAnnotations)
            .toArray(Annotation[][]::new);
        if(raw==target) return a;
        atArgAnnos=new HashMap<>(a.length);
        for(int ix = 0; ix < a.length; ix++)
            atArgAnnos.put(param[ix], a[ix]);
    }
    else throw new UnsupportedOperationException(
            "type variables, wildcard or arrays are not supported");
    raw.asSubclass(target);// throws if not assignable
    for(AnnotatedType aift: target.isInterface()? raw.getAnnotatedInterfaces():
                            new AnnotatedType[]{raw.getAnnotatedSuperclass()}) {
        Type ift=aift.getType();
        if(ift==target) return new Annotation[typeParameters.length][0]; // raw
        else {
            AnnotatedParameterizedType ifpt = (AnnotatedParameterizedType)aift;
            if(((ParameterizedType)ifpt.getType()).getRawType()!=target) continue;
            return Arrays.stream(ifpt.getAnnotatedActualTypeArguments())
                  .map(ta -> atArgAnnos.getOrDefault(ta.getType(), ta.getAnnotations()))
                  .toArray(Annotation[][]::new);
        }
    }
    throw new UnsupportedOperationException(
        t.getTypeName()+" does not (directly) extend or implement "+target);
}

static Annotation[][] getActualAnnotations(AnnotatedType at, Class<?> target) {
    Type[] typeParameters = target.getTypeParameters();
    if(typeParameters.length==0) return new Annotation[0][];
    Type t=at.getType();
    Map<Type,Annotation[]> atArgAnnos;
    Class<?> raw;
    if(t instanceof Class) {
        atArgAnnos=Collections.emptyMap();
        raw=(Class<?>)t;
        if(raw==target) return new Annotation[typeParameters.length][0];
    }
    else if(t instanceof ParameterizedType) {
        ParameterizedType pt=(ParameterizedType)t;
        raw=(Class<?>)pt.getRawType();
        Type[] param=raw.getTypeParameters();
        Annotation[][] a = Arrays
            .stream(((AnnotatedParameterizedType)at).getAnnotatedActualTypeArguments())
            .map(AnnotatedType::getAnnotations)
            .toArray(Annotation[][]::new);
        if(raw==target) return a;
        atArgAnnos=new HashMap<>(a.length);
        for(int ix = 0; ix < a.length; ix++)
            atArgAnnos.put(param[ix], a[ix]);
    }
    else throw new UnsupportedOperationException(
            "type variables, wildcard or arrays are not supported");
    raw.asSubclass(target);// throws if not assignable
    for(AnnotatedType aift: target.isInterface()? raw.getAnnotatedInterfaces():
                            new AnnotatedType[]{raw.getAnnotatedSuperclass()}) {
        Type ift=aift.getType();
        if(ift==target) return new Annotation[typeParameters.length][0]; // raw
        else {
            AnnotatedParameterizedType ifpt = (AnnotatedParameterizedType)aift;
            if(((ParameterizedType)ifpt.getType()).getRawType()!=target) continue;
            return Arrays.stream(ifpt.getAnnotatedActualTypeArguments())
                  .map(ta -> atArgAnnos.getOrDefault(ta.getType(), ta.getAnnotations()))
                  .toArray(Annotation[][]::new);
        }
    }
    throw new UnsupportedOperationException(
        t.getTypeName()+" does not (directly) extend or implement "+target);
}
interface AnotherExample<ID, KEY> extends Map<KEY, @Size(min=100) String> {
    ID getId();
}
AnotherExample<String, @Size(min=42) String> field;
System.out.print(field.getName()+"\t");
Annotation[][] a=getActualAnnotations(field.getAnnotatedType(), Map.class);
System.out.println("key: "+Arrays.toString(a[0])+", value: "+Arrays.toString(a[1]));