Why java classes do not inherit annotations from implemented interfaces?

65,534

Solution 1

I'd say the reason is that otherwise a multiple-inheritance problem would occur.

Example:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Inherited
public @interface Baz { String value(); }

public interface Foo{
    @Baz("baz") void doStuff();
}

public interface Bar{
    @Baz("phleem") void doStuff();
}

public class Flipp{
    @Baz("flopp") public void doStuff(){}
}

public class MyClass extends Flipp implements Foo, Bar{}

If I do this:

MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value()

what's the result going to be? 'baz', 'phleem' or 'flopp'?


For this reason, annotations on interfaces are rarely useful.

Solution 2

From the Javadoc for @Inherited:

Indicates that an annotation type is automatically inherited. If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type. This process will be repeated until an annotation for this type is found, or the top of the class hierarchy (Object) is reached. If no superclass has an annotation for this type, then the query will indicate that the class in question has no such annotation. 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.

On the other hand, JSR 305 validators do some sort of inheritance lookup. If you have a hierarchy of classes:

//Person.java
@Nonnull
 public Integer getAge() {...}

//Student.java (inherits from Person)
@Min(5)
public Integer getAge() {...}

Then the effective validations on Student.getAge() are @Nonnull @Min(5). @Nonnull has no @Inherited meta-annotation.

Share:
65,534

Related videos on Youtube

Boris Pavlović
Author by

Boris Pavlović

Interested in developing programming, concurrent model design skills, design patterns, refactoring, testing... Computer languages: java, javaScript, sql, fsp, erlang...

Updated on July 08, 2022

Comments

  • Boris Pavlović
    Boris Pavlović almost 2 years

    I'm using a Dependency Injection framework (Guice's AOP to intercept some method calls specifically). My class implements an interface and I would like to annotate the interface methods so the framework could select the right methods. Even if the annotation type is annotated with Inherited annotation implementing class doesn't inherit the annotation as stated in Inherited's java doc:

    Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.

    What could be the reason for this? Getting to know all interfaces that an object's class does implement in runtime is not that hard thing to do so there must be a good reason behind this decision.

  • Vishy
    Vishy over 13 years
    annotations on interfaces are only useful if you have a framework which supports them. BTW in this example getAnnotation() returns null ;)
  • Petr Janeček
    Petr Janeček about 12 years
    I don't know, people. In this case (if the typo wasn't there), I'd expect a The field value is ambiguous.-like compiler error just like with two interfaces declaring the same constant with different values. I know that this is not a field, but annotation values get all resolved at compile time, don't they? The feature we're missing here would be super-helpful in many cases. Sorry about reviving an old post, by the way :).
  • Sean Patrick Floyd
    Sean Patrick Floyd about 12 years
    @Slanec have a look at the way the Spring sources to see how the Spring guys worked around these problems. See AnnotationUtils.findAnnotation(method, annotationType)
  • Petr Janeček
    Petr Janeček about 12 years
    I was considering writing something similar to this. With some sort of simple caching, this seems like a way to go for me. Thanks! In the example above, it would find the Foo's annotation (MyClass doesn't have one, then Interfaces are searched and taken in the order in which they are after implements) and therefore print "baz". Cool.
  • wchargin
    wchargin about 11 years
    Should that be getAnnotation(Baz.class)?
  • Sean Patrick Floyd
    Sean Patrick Floyd about 11 years
    @WChargin true, it just took 2 years for someone to spot that typo :-)
  • Andrzej Purtak
    Andrzej Purtak about 8 years
    This one should be the selected answer
  • Oleg Mikheev
    Oleg Mikheev over 7 years
    your example contradict your answer, which says that @Inherited has no effect on anything other than class
  • Carlos Parker
    Carlos Parker over 5 years
    @Inherited only work when you use the annotation on Class
  • cdalxndr
    cdalxndr over 3 years
    What about answering OP's question about annotations on interfaces!?