Java在基类中添加注解对子类无效问题

Author Avatar
MoonChen 2月 15, 2017

有项功能,需要对当前的class添加注解,由此来决定是否要开启功能。如下:

1
2
3
4
@Retention(RetentionPolicy.RUNTIME)
public @interface Itest {
int getInfo() default 1;
}
1
2
3
4
5
6
@Itest
public class A {
}
...
Itest iTest = classA.getClass().getAnnotation(Itest.class);

问题出现在 当 A为父类时,子类B无法获取到这个注解。

1
2
3
4
@Itest
public class Parent {}
public class Child extends Parent {}

如上,对Parent添加注解,使用Child.class.getAnnotation(Itest.class)则返回了null

Why?

翻了下getAnnotation(Class<A> annotationClass)源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
if (annotationClass == null)
throw new NullPointerException();
A annotation = getDeclaredAnnotation(annotationClass);
if (annotation != null) {
return annotation;
}
if (annotationClass.isDeclaredAnnotationPresent(Inherited.class)) {
for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
annotation = sup.getDeclaredAnnotation(annotationClass);
if (annotation != null) {
return annotation;
}
}
}
return null;
}

可以看到, annotationClass.isDeclaredAnnotationPresent(Inherited.class)。如果申明了Inherited.class注解,那么会递归的调用父类方法去查找注解。

而每次查找则会调用getDeclaredAnnotation方法来查找。

###getDeclaredAnnotation
这是一个native方法,java8 上有对该函数的说明。

1
2
Returns:
this element's annotation for the specified annotation type if directly present on this element, else null

总结

对于java.lang.annotation.Inherited 表示可以从超类型中查找注解。

getAnnotations
getAnnotationsByType(Class<T> annotationClass)
getAnnotation(Class<A> annotationClass)
isAnnotationPresent(Class<? extends Annotation> annotationType)

在使用如上API时,如果指定了Inherited注解,则会在超类中查询 注解类型。