[英]How to parse Java annotation in generic type?
我有这样的注释:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface NotNull {}
并有一个 class:
class Main{
List<@NotNull String> list;
}
我应该如何使用反射 API 解析这个注释?
注释显示在generics 部分中。 这立即意味着两件事:
如果类型位于不属于签名的位置(因此,局部变量声明或强制转换,或new Foo<X>()
中的 X 等 - 那么它就消失了,generics 被删除在这种情况下。根本没有办法引用它,在运行时你再也看不到它了。
如果类型是签名的一部分(它是字段的类型、方法的返回类型、参数的类型或您extends
或implements
的东西),那么它会在运行时保留,但是,所有常见的获取这些东西的方法,例如someJLReflectFieldInstance.getType()
,总是返回一个java.lang.Class
实例和 generics 实例,所以你也可以使用这些方法。
如果你在#1 船上,答案马上就结束了:不可能。
如果你在#2 船上,这是可能的。 首先,找到getGenericType()
方法 - 一种变体方法,它也返回您想要的类型,但作为Type
而不是Class
。 对于jlreflect.Field
,该方法是getGenericType()
。 类似的方法存在于方法返回类型、参数类型等。 然后意识到这还不够——这让你得到了<>
中的东西,但是去掉了所有的注释。 继续寻找,你会找到真正的赢家。 对于jlr.Field
,即getAnnotatedType
。
你现在有一个AnnotatedType
,它看起来几乎完全没用:它几乎没有任何方法。 这是一个包罗万象的标记式界面,因为对于 java 中的类型有不同的想法。 ?
在这个意义上是一种类型,因为它可以出现在类型出现的地方: List<?>
。 也是? extends Map<?, Set<String>>
? extends Map<?, Set<String>>
。 T
也是如此, String
也是如此, int[]
也是如此, double
也是如此。 它们几乎都可以被注释。
通常的解决方案是强制转换和instanceof
检查。 List<@NonNull String>
类的东西是java.lang.reflect.AnnotatedParameterizedType
。 所以让我们投射并继续。 这个接口有getAnnotatedActualTypeArguments()
方法,它再次返回那个无用的AnnotatedType
的数组: 毕竟,它可能是List<?>
、 List<String>
、 List<T>
、 List<? extends Stuff>
List<? extends Stuff>
等。
@NonNull String
将是java.lang.reflect.AnnotatedType
的实例。
让我们把它们放在一起。 把它扔到一个文件中,编译它,然后运行它:
import java.lang.annotation.*;
import java.util.List;
import java.lang.reflect.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
@interface NonNull {}
class Test {
List<@NonNull String> example;
public static void main(String[] args) throws Exception {
Field f = Test.class.getDeclaredField("example");
AnnotatedParameterizedType listType =
(AnnotatedParameterizedType) f.getAnnotatedType();
AnnotatedType annType = (AnnotatedType)
listType.getAnnotatedActualTypeArguments()[0];
for (Annotation ann : annType.getAnnotations()) {
System.out.println("Annotation found: " + ann);
}
}
}
javac Test.java; java Test
> Annotation found: @NonNull()
注意:如果你知道你在找什么,上面的内容还不错,但是如果你试图处理大量可能的类型类型(呵呵),你很快就会遇到一大堆混乱的代码。 我不直接知道图书馆可以提供帮助,但您可能想研究它或写一些东西; 为这些东西设置访问者模式并不难。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.