How do Java method annotations work in conjunction with method overriding?

后端 未结 4 1297
清酒与你
清酒与你 2020-11-28 06:39

I have a parent class Parent and a child class Child, defined thus:

class Parent {
    @MyAnnotation("hello")
    void foo         


        
相关标签:
4条回答
  • 2020-11-28 06:50

    You found your answer already: there is no provision for method-annotation inheritance in the JDK.

    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);
    }
    
    0 讨论(0)
  • 2020-11-28 07:02

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

    Annotation 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.

    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.

    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. So, in the example above, if the MyAnnotation type had the @Inherited attribute, then Sub would have the MyAnnotation annotation.

    @Inherited annotations are not inherited when used to annotate anything other than a type. A type that implements one or more interfaces never inherits any annotations from the interfaces it implements.

    0 讨论(0)
  • 2020-11-28 07:09

    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. Here is a more complete version of Saintali's answer that I'm currently using:

    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;
        }
    }
    
    0 讨论(0)
  • 2020-11-28 07:11

    Using Spring Core you can resolve with

    AnnotationUtils.java

    0 讨论(0)
提交回复
热议问题