繁体   English   中英

如何访问方法参数的泛型类型参数上的注释?

[英]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) {}
    }
}

在 Ideone 上演示

@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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM