Почему классы Java не наследуют аннотации от реализованных интерфейсов? - PullRequest
102 голосов
/ 20 января 2011

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

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

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

Ответы [ 2 ]

123 голосов
/ 20 января 2011

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

Пример:

@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»?


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

32 голосов
/ 01 февраля 2013

Из Javadoc для @ Inherited:

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

С другой стороны, валидаторы 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 метааннотации.

...