Java方法注释如何与方法重写一起使用?

时间:2012-04-10 03:04:24

标签: java inheritance annotations override

我有一个父类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继承一起使用。

4 个答案:

答案 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,您可以使用

解决

AnnotationUtils.java

答案 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;
    }
}