运行时是否可以访问类型参数的注解?
Are annotations on a type parameter accessible in runtime?
Java 8 允许这样的事情:
public List<@NonNull String> names;
但是有没有办法在运行时访问这个注解,或者它只对编译器插件可用?
有新的 Method#getAnnotatedReturnType
可以访问 return 类型的注解,所以我希望 ParameterizedType
现在有类似 getActualAnnotatedTypeArguments
的东西可以做同样的事情对于泛型类型参数,但它不存在...
确实有一个方法 getAnnotatedActualTypeArguments
但在 AnnotatedParameterizedType
中,而不是在 ParameterizedType
我正在寻找它的地方。
新的 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 的末尾以获取处理其他场景(如类型变量、通配符类型和数组)的示例。
这是我的解决方案:
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>");
Java 8 允许这样的事情:
public List<@NonNull String> names;
但是有没有办法在运行时访问这个注解,或者它只对编译器插件可用?
有新的 Method#getAnnotatedReturnType
可以访问 return 类型的注解,所以我希望 ParameterizedType
现在有类似 getActualAnnotatedTypeArguments
的东西可以做同样的事情对于泛型类型参数,但它不存在...
确实有一个方法 getAnnotatedActualTypeArguments
但在 AnnotatedParameterizedType
中,而不是在 ParameterizedType
我正在寻找它的地方。
新的 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 的末尾以获取处理其他场景(如类型变量、通配符类型和数组)的示例。
这是我的解决方案:
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>");