是否可以在运行时访问类型参数上的注释?

时间:2016-07-20 16:49:10

标签: java annotations java-8 bean-validation

Java 8允许以下内容:

public List<@NonNull String> names;

但是有没有办法在运行时访问这个注释,或者它只适用于编译器插件?

有新的Method#getAnnotatedReturnType提供对返回类型的注释的访问权限,所以我希望ParameterizedType现在可以像getActualAnnotatedTypeArguments那样对通用做同样的事情类型参数,但它不存在...

3 个答案:

答案 0 :(得分:4)

新API延续了需要大量instanceof和类型转换的传统:

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.*;

public class AnnoTest {
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE_USE)
    @interface NonNull {}

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE_USE)
    @interface NonEmpty {}

    List<@NonNull String> list;
    Map<@NonNull Integer, @NonNull @NonEmpty Set<String>> map;
    Object plain;

    public static void main(String[] args) throws ReflectiveOperationException {
        for(Field field: AnnoTest.class.getDeclaredFields()) {
            AnnotatedType at = field.getAnnotatedType();
            System.out.println(formatType(at)+" "+field.getName());
        }
    }
    static CharSequence formatType(AnnotatedType type) {
        StringBuilder sb=new StringBuilder();
        for(Annotation a: type.getAnnotations()) sb.append(a).append(' ');
        if(type instanceof AnnotatedParameterizedType) {
            AnnotatedParameterizedType apt=(AnnotatedParameterizedType)type;
            sb.append(((ParameterizedType)type.getType()).getRawType().getTypeName());
            sb.append(Stream.of(apt.getAnnotatedActualTypeArguments())
                .map(AnnoTest::formatType).collect(Collectors.joining(",", "<", ">")));
        }
        else sb.append(type.getType().getTypeName());
        return sb;
    }
}

另请参阅this answer的结尾,以获取处理其他方案(如类型变量,通配符类型和数组)的示例。

答案 1 :(得分:3)

确实有一种方法getAnnotatedActualTypeArguments,但在AnnotatedParameterizedType中,而不是ParameterizedType我正在寻找的方法。

答案 2 :(得分:0)

这是我的解决方案:

 Method method = context.getMethod();
    Annotation[][] annotations = method.getParameterAnnotations();
    Object[] parameterValues = context.getParameters();
    for (int i = 0; i < annotations.length; i++) {
        for (int j = 0; j < annotations[i].length; j++) {
            if (annotations[i][j] instanceof <YourAnnotation>) {
                return (String) parameterValues[j];
            }
        }
    }
    throw new IncompleteAnnotationException(<YourAnnotation>.class, "<YourAnnotation>");