Почему классы java не наследуют аннотации от реализованных интерфейсов?

Я использовал Guice AOP для перехвата вызовов некоторых методов. Мой класс реализует интерфейс, и я хотел бы аннотировать методы интерфейса, чтобы Guice мог выбрать правильные методы. Даже если тип аннотации аннотируется Inherited, класс реализации аннотации не наследует аннотацию, как указано в Inherited java doc:

Обратите внимание, что эта мета-аннотация только вызывает аннотации унаследованные от суперклассов; аннотации по реализованным интерфейсам не имеют эффекта.

Что может быть причиной этого? Знакомство со всеми интерфейсами, которые класс объектов реализует во время выполнения, не так уж сложно, поэтому для этого решения должна быть веская причина.

Ответ 1

Я бы сказал, причина в том, что в противном случае возникла проблема множественного наследования.

Пример:

@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{}

Если я это сделаю:

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

каким будет результат? 'baz', 'phleem' или 'flopp'?


По этой причине аннотации на интерфейсах редко бывают полезными.

Ответ 2

Из Javadoc для @Inherited:

Указывает, что тип аннотации автоматически унаследован. Если Наследуемая мета-аннотация присутствует в типе аннотации объявление, и пользователь запрашивает тип аннотации в классе Объявление и декларация класса не содержат аннотации для этого тип, то класс суперкласса автоматически будет запрашиваться для тип аннотации. Этот процесс будет повторяться до аннотации для этого типа, или вершина иерархии классов (Object) является достиг. Если у суперкласса нет аннотации для этого типа, запрос указывает, что этот класс не имеет такой аннотации. Обратите внимание: этот мета-аннотационный тип не действует, если аннотированный type используется для аннотации ничего, кроме класса. Отметим также, что эта мета-аннотация только приводит к унаследованию аннотаций из суперклассы; аннотации на реализованных интерфейсах не влияют.

С другой стороны, валидаторы JSR 305 выполняют какой-то поиск наследования. Если у вас есть иерархия классов:

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

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

Тогда эффективные валидации на Student.getAge() равны @Nonnull @Min(5). @Nonnull не имеет мета-аннотации @Inherited.