简体   繁体   English

Java 方法注释如何与方法重写一起工作?

[英]How do Java method annotations work in conjunction with method overriding?

I have a parent class Parent and a child class Child , defined thus:我有一个 parent class Parent和一个 child class Child ,定义如下:

class Parent {
    @MyAnnotation("hello")
    void foo() {
        // implementation irrelevant
    }
}
class Child extends Parent {
    @Override
    foo() {
        // implementation irrelevant
    }
}

If I obtain a Method reference to Child::foo , will childFoo.getAnnotation(MyAnnotation.class) give me @MyAnnotation ?如果我获得对Child::fooMethod引用, childFoo.getAnnotation(MyAnnotation.class)会给我@MyAnnotation吗? Or will it be null ?还是null

I'm interested more generally in how or whether annotation works with Java inheritance.我对注释如何或是否与 Java inheritance 一起工作更感兴趣。

Copied verbatim from http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations.html#annotation-inheritance :http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations.html#annotation-inheritance逐字复制:

Annotation Inheritance批注Inheritance

It is important to understand the rules relating to inheritance of annotations, as these have a bearing on join point matching based on the presence or absence of annotations.了解与注释 inheritance 有关的规则很重要,因为这些规则与基于注释存在与否的连接点匹配有关。

By default annotations are not inherited.默认情况下,注释不会被继承。 Given the following program给定以下程序

        @MyAnnotation
        class Super {
          @Oneway public void foo() {}
        }

        class Sub extends Super {
          public void foo() {}
        }

Then Sub does not have the MyAnnotation annotation, and Sub.foo() is not an @Oneway method, despite the fact that it overrides Super.foo() which is.然后Sub没有MyAnnotation注释,并且Sub.foo()不是@Oneway方法,尽管它覆盖Super.foo()这是。

If an annotation type has the meta-annotation @Inherited then an annotation of that type on a class will cause the annotation to be inherited by sub-classes.如果注释类型具有元注释@Inherited ,则 class 上该类型的注释将导致该注释被子类继承。 So, in the example above, if the MyAnnotation type had the @Inherited attribute, then Sub would have the MyAnnotation annotation.因此,在上面的示例中,如果MyAnnotation类型具有@Inherited属性,则Sub将具有MyAnnotation注释。

@Inherited annotations are not inherited when used to annotate anything other than a type. @Inherited注释在用于注释除类型以外的任何内容时不会被继承。 A type that implements one or more interfaces never inherits any annotations from the interfaces it implements.实现一个或多个接口的类型永远不会从它实现的接口继承任何注释。

You found your answer already: there is no provision for method-annotation inheritance in the JDK.您已经找到了答案:JDK 中没有方法注释 inheritance 的规定。

But climbing the super-class chain in search of annotated methods is also easy to implement:但是攀登超类链以搜索带注释的方法也很容易实现:

/**
 * 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);
}

Using Spring Core you can resolve with使用 Spring 核心你可以解决

AnnotationUtils.java AnnotationUtils.java

While the answer to the question as asked is that Java's Method.getAnnotation() does not consider overridden methods, sometimes it is useful to find these annotations.虽然所问问题的答案是 Java 的Method.getAnnotation()不考虑覆盖的方法,但有时找到这些注释很有用。 Here is a more complete version of Saintali's answer that I'm currently using:这是我目前正在使用的 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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM