我有一个父类Parent
和一个子类Child
,由此定义:
class Parent {
@MyAnnotation("hello")
void foo() {
// implementation irrelevant
}
}
class Child {
@Override
foo() {
// implementation irrelevant
}
}
如果我获得了对Method
的{{1}}引用,那么Child::foo
会给我childFoo.getAnnotation(MyAnnotation.class)
吗?或者是@MyAnnotation
?
我更感兴趣的是注释如何或是否与Java继承一起使用。
答案 0 :(得分:70)
从http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations.html#annotation-inheritance逐字复制:
注释继承
理解与注释继承相关的规则非常重要,因为它们会根据注释的存在与否来影响连接点匹配。
默认情况下,不会继承注释。鉴于以下计划
@MyAnnotation
class Super {
@Oneway public void foo() {}
}
class Sub extends Super {
public void foo() {}
}
然后
Sub
没有MyAnnotation
注释,而Sub.foo()
不是@Oneway
方法,尽管它会覆盖Super.foo()
。@Inherited
如果注释类型具有元注释
当用于注释除类型之外的任何内容时,MyAnnotation
,则类上该类型的注释将导致注释被子类继承。因此,在上面的示例中,如果@Inherited
类型具有Sub
属性,则MyAnnotation
将具有@Inherited
注释。{{1}}注释不会被继承。实现一个或多个接口的类型永远不会从它实现的接口继承任何注释。
答案 1 :(得分:10)
您已经找到了答案:JDK中没有提供方法注释继承。
但是,攀登超级链以寻找带注释的方法也很容易实现:
/**
* Climbs the super-class chain to find the first method with the given signature which is
* annotated with the given annotation.
*
* @return A method of the requested signature, applicable to all instances of the given
* class, and annotated with the required annotation
* @throws NoSuchMethodException If no method was found that matches this description
*/
public Method getAnnotatedMethod(Class<? extends Annotation> annotation,
Class c, String methodName, Class... parameterTypes)
throws NoSuchMethodException {
Method method = c.getMethod(methodName, parameterTypes);
if (method.isAnnotationPresent(annotation)) {
return method;
}
return getAnnotatedMethod(annotation, c.getSuperclass(), methodName, parameterTypes);
}
答案 2 :(得分:7)
使用Spring Core,您可以使用
解决答案 3 :(得分:2)
虽然问题的答案是Java的Method.getAnnotation()
不考虑重写方法,但有时查找这些注释很有用。以下是我目前正在使用的更完整版的Saintali答案:
public static <A extends Annotation> A getInheritedAnnotation(
Class<A> annotationClass, AnnotatedElement element)
{
A annotation = element.getAnnotation(annotationClass);
if (annotation == null && element instanceof Method)
annotation = getOverriddenAnnotation(annotationClass, (Method) element);
return annotation;
}
private static <A extends Annotation> A getOverriddenAnnotation(
Class<A> annotationClass, Method method)
{
final Class<?> methodClass = method.getDeclaringClass();
final String name = method.getName();
final Class<?>[] params = method.getParameterTypes();
// prioritize all superclasses over all interfaces
final Class<?> superclass = methodClass.getSuperclass();
if (superclass != null)
{
final A annotation =
getOverriddenAnnotationFrom(annotationClass, superclass, name, params);
if (annotation != null)
return annotation;
}
// depth-first search over interface hierarchy
for (final Class<?> intf : methodClass.getInterfaces())
{
final A annotation =
getOverriddenAnnotationFrom(annotationClass, intf, name, params);
if (annotation != null)
return annotation;
}
return null;
}
private static <A extends Annotation> A getOverriddenAnnotationFrom(
Class<A> annotationClass, Class<?> searchClass, String name, Class<?>[] params)
{
try
{
final Method method = searchClass.getMethod(name, params);
final A annotation = method.getAnnotation(annotationClass);
if (annotation != null)
return annotation;
return getOverriddenAnnotation(annotationClass, method);
}
catch (final NoSuchMethodException e)
{
return null;
}
}