14

I have an interface with an annotated method. The annotation is marked with @Inherited, so I expect an implementor to inherit it. However, it is not the case:

Code:

import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; import java.util.Arrays; public class Example { public static void main(String[] args) throws SecurityException, NoSuchMethodException { TestInterface obj = new TestInterface() { @Override public void m() {} }; printMethodAnnotations(TestInterface.class.getMethod("m")); printMethodAnnotations(obj.getClass().getMethod("m")); } private static void printMethodAnnotations(Method m) { System.out.println(m + ": " + Arrays.toString(m.getAnnotations())); } } interface TestInterface { @TestAnnotation public void m(); } @Retention(RetentionPolicy.RUNTIME) @Inherited @interface TestAnnotation {} 

The above code prints:

public abstract void annotations.TestInterface.m(): [@annotations.TestAnnotation()]

public void annotations.Example$1.m(): []

So the question is why does not the obj.m() have @TestAnnotation despite that it implements a method marked with @TestAnnotation which is @Inherited?

6
  • 1
    The answer was right there in the documentation of @Inherited as pointed out by @AbhinavSakar and @Gilberto. Sorry about that. I did quite a bit of experimentation but missed the obvious - the docs. Commented Sep 14, 2012 at 17:08
  • By the way, any idea on what is the reason for such a design decision? I would expect the meta-annotation to work on methods too. Commented Sep 14, 2012 at 17:09
  • No problem, it is surprising that super-classes are treated differently from super-interfaces. That's why some frameworks (such as Spring) ship with reflection utilities that also query the super interfaces. Commented Sep 14, 2012 at 17:10
  • Just out of curiosity, which utility in Spring is that? Commented Sep 14, 2012 at 17:14
  • org.springframework.core.type.classreading.MetadataReader. Commented Sep 14, 2012 at 17:25

3 Answers 3

33

From the javadocs of java.lang.annotation.Inherited:

Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

Sign up to request clarification or add additional context in comments.

3 Comments

Woa, answered at same time =)
I upvoted both, but had to accept only one answer. Sorry, @Gilberto, Abhinav was a tiny bit quicker :)
No problem, we are here to help ;-)
23

From the @Inherited javadoc:

Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class. Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.`

In summary, it doesn't apply to methods.

Comments

3

Alternatively, you can use reflection to derive the same information. The method printMethodAnnotations can be rewritten as:

private static void printMethodAnnotations(Method m) { Class<?> methodDeclaredKlass = m.getDeclaringClass(); List<Class<?>> interfases = org.apache.commons.lang3.ClassUtils.getAllInterfaces(methodDeclaredKlass); List<Annotation> annotations = new ArrayList<>(); annotations.addAll(Arrays.asList(m.getAnnotations())); for (Class<?> interfase : interfases) { for (Method interfaseMethod : interfase.getMethods()) { if (areMethodsEqual(interfaseMethod, m)) { annotations.addAll(Arrays.asList(interfaseMethod.getAnnotations())); continue; } } } System.out.println(m + "*: " + annotations); } private static boolean areMethodsEqual(Method m1, Method m2) { // return type, Modifiers are not required to check, if they are not appropriate match then it will be a compile // time error. This needs enhancements for Generic types parameter ? return m1.getName().equals(m2.getName()) && Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes()); } 

1 Comment

thanks.. worked for me. But i could find same using spring core's AnnotationUtils. Here is maven dep

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.