Java 使用class.getDeclaredMethod反射方法时不存在批注

Java 使用class.getDeclaredMethod反射方法时不存在批注,java,reflection,annotations,java-8,Java,Reflection,Annotations,Java 8,我正在使用反射编写一些单元测试,从方法参数中检索注释时遇到问题 我声明这个接口: private interface Provider { void mock(@Email String email); } 我试图反映这种方法,如下所示: Class stringClass = String.class; Method method = Provider.class.getDeclaredMethod("mock", String.class); Annotated

我正在使用反射编写一些单元测试,从方法参数中检索注释时遇到问题

我声明这个接口:

private interface Provider {
    void mock(@Email String email);
}
我试图反映这种方法,如下所示:

Class stringClass = String.class;
Method method = Provider.class.getDeclaredMethod("mock", String.class);
AnnotatedType annotatedType = method.getAnnotatedParameterTypes()[0];
Annotation annotation = annotatedType.getAnnotation(Annotation.class);
我希望
annotation
变量包含
@Email
annotation的一个实例,但是它的值是
null

即使是这个简单的检查也会返回
false

method.isAnnotationPresent(Email.class)
那么,在反映方法时,如何检索特定参数的注释呢

更新
似乎为了检索参数注释,我需要调用
method.getParameterAnnotations()
。但问题是,我不知道什么注释属于什么方法。

如果希望注释在程序执行期间可见,则需要使用
@Retention(RetentionPolicy.RUNTIME)
对其进行注释:

专用接口提供程序{
void mock(@Email String Email);
}
@保留(RetentionPolicy.RUNTIME)
public@interface电子邮件{}
@试验
public void test_annotation_existence()引发NoSuchMethodException{
方法=Provider.class.getDeclaredMethod(“mock”,String.class);
批注[]firstParameterAnnotationsArray=method.getParameterAnnotations()[0];
布尔值isAnnotationPresent=isAnnotationPresent(第一个参数AnnotationsArray,Email.class);
Assert.assertTrue(“注释不存在!”,isAnnotationPresent);
}
私有布尔值isAnnotationPresent(Annotation[]annotationsArray,类clazz){
if(annotationsArray==null)
抛出新的IllegalArgumentException(“请传递非空的注释数组”);
对于(int i=0;i
您必须区分Java 8类型注释和(自Java 5以来)参数注释。类型注释的关键是,您必须声明可以显式地将注释用作类型注释

考虑以下示例:

public class AnnoTest {
    @Retention(RetentionPolicy.RUNTIME)
    @interface Email {}

    void example(@Email String arg) {}

    public static void main(String[] args) throws ReflectiveOperationException {
        Method method=AnnoTest.class.getDeclaredMethod("example", String.class);
        System.out.println("parameter type annotations:");
        AnnotatedType annotatedType = method.getAnnotatedParameterTypes()[0];
        //Annotation annotation = annotatedType.getAnnotation(Annotation.class);
        System.out.println(Arrays.toString(annotatedType.getAnnotations()));
        System.out.println("parameter annotations:");
        System.out.println(Arrays.toString(method.getParameterAnnotations()[0]));
    }
}
它会打印出来

参数类型注释:
[]
参数注释:
[@AnnoTest$Email()]
在这种情况下,注释是参数的属性

现在将其更改为(注意
@Target

哪个会打印

参数类型注释:
[@AnnoTest$Email()]
参数注释:
[]
相反。现在,注释是参数类型的一个特征,即
String
。从概念上讲,该方法的参数类型现在是
@Email String
(这似乎是最合乎逻辑的选择,因为它允许声明类型,如
List
,但您必须了解这些新类型注释是如何工作的,并且它不与Java 8之前的库一起工作)

在为参数和类型使用启用注释时必须小心,因为这可能会创建不明确的注释。 如果发生这种情况,编译器将同时记录参数和类型的注释,例如。 当您将示例中的目标更改为
@target({ElementType.TYPE\u USE,ElementType.PARAMETER})
时,它将打印

参数类型注释:
[@AnnoTest$Email()]
参数注释:
[@AnnoTest$Email()]

类似的问题可能会出现在方法返回类型上。为“类型使用”和方法启用注释时的字段类型,以及。字段。

电子邮件已使用保留批注进行批注。我应该指出这一点。请看一下代码的其余部分。
方法.getParameterAnnotations()[0]
不返回
注释类型
,而是返回可循环使用的
注释
数组。如果
@Email
已在
运行时保留
,请发布一个重新生成您的问题的。
public class AnnoTest {
    @Retention(RetentionPolicy.RUNTIME)
    @interface Email {}

    void example(@Email String arg) {}

    public static void main(String[] args) throws ReflectiveOperationException {
        Method method=AnnoTest.class.getDeclaredMethod("example", String.class);
        System.out.println("parameter type annotations:");
        AnnotatedType annotatedType = method.getAnnotatedParameterTypes()[0];
        //Annotation annotation = annotatedType.getAnnotation(Annotation.class);
        System.out.println(Arrays.toString(annotatedType.getAnnotations()));
        System.out.println("parameter annotations:");
        System.out.println(Arrays.toString(method.getParameterAnnotations()[0]));
    }
}
public class AnnoTest {
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE_USE)
    @interface Email {}

    void example(@Email String arg) {}

    public static void main(String[] args) throws ReflectiveOperationException {
        Method method=AnnoTest.class.getDeclaredMethod("example", String.class);
        System.out.println("parameter type annotations:");
        AnnotatedType annotatedType = method.getAnnotatedParameterTypes()[0];
        //Annotation annotation = annotatedType.getAnnotation(Annotation.class);
        System.out.println(Arrays.toString(annotatedType.getAnnotations()));
        System.out.println("parameter annotations:");
        System.out.println(Arrays.toString(method.getParameterAnnotations()[0]));
    }
}