Field#getAnnotations()和Field#getDeclaredAnnotations()之间的区别

时间:2013-08-29 13:25:38

标签: java inheritance annotations

JavaDoc说:

AccessibleObject#getDeclaredAnnotations

  

返回直接出现在此元素上的所有注释。与此接口中的其他方法不同,此方法忽略继承的注释。 (如果此元素上没有直接出现注释,则返回长度为零的数组。)此方法的调用者可以自由修改返回的数组;它对返回给其他调用者的数组没有影响。

Field#getAnnotations

  

返回此元素上的所有注释。 (如果此元素没有注释,则返回长度为零的数组。)此方法的调用者可以自由修改返回的数组;它对返回给其他调用者的数组没有影响。

由于getAnnotations是从类java.lang.reflect.AccessibleObject继承的,因此让Field对象可以访问它。

据我所知,getDeclaredAnnotations忽略了继承的注释,它们之间的唯一区别。 我在处理类时得到的,但据我所知,Fields不能继承注释。

3 个答案:

答案 0 :(得分:9)

查看源代码可以得到答案:

摘自java.lang.reflect.AccessibleObject

/**
 * @since 1.5
 */
public Annotation[] getAnnotations() { 
    return getDeclaredAnnotations();
}

/**
 * @since 1.5
 */
public Annotation[] getDeclaredAnnotations()  {
    throw new AssertionError("All subclasses should override this method");
}

Field does not override getAnnotations()getDeclaredAnnotations()被调用。

因此,在java.lang.reflect.Field对象上调用时,两种方法都会相同。 (所以JavaDoc在我看来是错的)

另一种情况是java.lang.Class,它会覆盖这两种方法(并且它会执行JavaDoc所说的内容;)):

/**
 * @since 1.5
 */
public Annotation[] getAnnotations() { 
    initAnnotationsIfNecessary();
    return AnnotationParser.toArray(annotations);
}

/**
 * @since 1.5
 */
public Annotation[] getDeclaredAnnotations()  {
    initAnnotationsIfNecessary();
    return AnnotationParser.toArray(declaredAnnotations);
}

答案 1 :(得分:2)

getDeclaredAnnotations()仅提供直接实现的注释,因为getAnnotations()从其父类提供直接实现和可继承的注释(@Inherited)。

答案 2 :(得分:0)

恰恰相反。 getDeclaredAnnotations() - 正如文档所说 - 是唯一忽略继承注释的方法。

以下是解释差异的片段:

public class Test1 {
    public static void main(String[] args) {
        Test3 test = new Test3();

        for (Annotation annotation : test.getClass().getAnnotations()) {
            System.out.println("Class getAnnotations: " + annotation);
        }

        for (Annotation annotation : test.getClass().getDeclaredAnnotations()) {
            System.out.println("Class getDeclaredAnnotations: " + annotation);
        }

        for (Field field : test.getClass().getFields()) {
            for (Annotation annotation : field.getAnnotations()) {
                System.out.println("Field getAnnotations: " + annotation);
        }

        for (Annotation annotation : field.getDeclaredAnnotations()) {
            System.out.println("Field getDeclaredAnnotations: " + annotation);
        }
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface CustomAnnotation {
    String value();
}

@CustomAnnotation("Class")
class Test2 {
    @CustomAnnotation("Field") public String testString;
}

 class Test3 extends Test2 {} 

输出将是`getAnnotations:

Class getAnnotations: @test.CustomAnnotation(value=Class)
Field getAnnotations: @test.CustomAnnotation(value=Field)
Field getDeclaredAnnotations: @test.CustomAnnotation(value=Field)

您看到Class getDeclaredAnnotations()为空,因为类Test3本身没有注释,只有Test2中的继承注释。

来自@Inherited的Javadoc:

  

表示自动继承注释类型。如果继承的元注释存在于注释类型声明,并且用户查询上一类声明注释类型,类声明没有注释这种类型,那么类的父类将自动查询的注释类型。将重复此过程,直到找到此类型的注释,或者到达类层次结构(对象)的顶部。如果没有超类具有此类型的注释,则查询将指示相关类没有此类注释。请注意,如果使用带注释的类型来注释除类之外的任何内容,则此元注释类型不起作用。另请注意,此元注释仅导致注释从超类继承;已实现的接口上的注释无效。