[英]How to access an annotation on a generic type parameter of a method argument?
假设我想使用反射检查以下类:
class Foo {
void bar(List<@Important String> b) {}
}
请注意, @Important
注释不在参数本身上(然后我可以使用Method.getParameterAnnotations()
),而是在其类型参数上(当注释声明为具有ElementType.TYPE_USE
时允许)。
有没有办法在 Java 11 中读取此类注释?
不幸的是,反射 API 的这部分非常糟糕。 基本类型没有必要的查询方法,也没有访问者 API 或类似的东西。 因此,任何试图进行完整自省的代码都别无选择,只能执行大量的instanceof
检查,以处理所有可能的情况。
如果您事先知道该方法的类型应该是参数化类型,并且只想检查其第一个类型参数的注释,则可以更简单一些,忽略所有其他可能的情况:
import java.lang.annotation.*;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.Method;
import java.util.*;
public class Main {
public static void main(String[] args) throws NoSuchMethodException {
Method m = Foo.class.getDeclaredMethod("bar", List.class);
var at = m.getAnnotatedParameterTypes()[0];
var ata = ((AnnotatedParameterizedType)at).getAnnotatedActualTypeArguments()[0];
// get all annotations
for(var a: ata.getAnnotations()) {
System.out.println(a);
}
// or check the presence of a known annotation
System.out.println(ata.getAnnotation(Important.class) != null);
}
class Foo {
void bar(List<@Important String> b) {}
}
}
@Important()
true
TL;DR — 请参阅此答案,讨论类型参数、类型变量和类型参数之间的细微差别。
长篇大论的版本
„ ...注意
@Important
注释是...在其类型参数上... “
在你的Foo
声明中......
class Foo {
void bar(List<@Important String> b) {}
}
… String
不是类型参数。 它也不是类型变量。 在您的代码段中, String
是一个类型参数。
尽管我原先说ReferenceType
类型参数不能有注释(事实证明它们可以),但我坚持更正,但我将把这些 JLS 作品留在这里以保持谦虚……
4.5.1. 参数化类型的类型参数
类型参数可以是引用类型或通配符。 在只需要有关类型参数的部分知识的情况下,通配符很有用。
TypeArguments:
< TypeArgumentList >
TypeArgumentList:
TypeArgument
{, TypeArgument}
TypeArgument:
ReferenceType
Wildcard
Wildcard:
{Annotation}
?
[WildcardBounds]
WildcardBounds:
extends
ReferenceType
super
ReferenceType
为完整起见,JLS 生成的类型参数……
4.4. 类型变量
类型变量是在类、接口、方法和构造函数体中用作类型的非限定标识符。
类型变量由泛型类、接口、方法或构造函数的类型参数的声明引入......
TypeParameter:
{TypeParameterModifier} TypeIdentifier [TypeBound]:
TypeParameterModifier:
Annotation
…
虽然我从未在野外看到过一个——直到今天——前面的 JLS 产品证实了你的代码片段中带注释的String
类型参数确实是合法的 Java。 每天学些新东西!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.