Маркерная аннотация по сравнению с интерфейсом маркера

Прочитав о интерфейсах Marker, я наткнулся на следующий сайт: Пункт 37: Использовать интерфейсы маркеров для определения типов
Здесь, по словам Джошуа Блоха, есть два преимущества интерфейсов Marker над аннотациями Marker.

  • Интерфейсы маркеров определяют тип, который реализуется экземплярами маркированный класс; маркерных аннотаций нет. Существование этого type позволяет вам ловить ошибки во время компиляции, которые вы не могли если вы использовали аннотацию маркера.

  • Еще одно преимущество интерфейсов маркеров над аннотациями маркеров что они могут быть нацелены более точно. Если тип аннотации объявленный с таргетингом ElementType.TYPE, он может быть применен к любому класса или интерфейса. Предположим, что у вас есть маркер, который применим только для реализаций определенного интерфейса. Если вы его определите как интерфейс маркера, вы можете расширить его интерфейс до который он применим, гарантируя, что все маркированные типы также подтипы единственного интерфейса, к которому он применим.

ОК, первая точка понята, но я не уверен, правильно ли понял второй пункт:

Если тип аннотации объявлен с целевым ElementType.TYPE, он может применяться к любому классу или интерфейсу.

Аналогично, если у меня есть интерфейс маркера, это тоже можно применить к любому классу или интерфейсу. Разве это не говорит то же самое о маркерных аннотациях и интерфейсах маркеров? Как можно ориентировать интерфейс маркера более точно?

Второй пункт также указывает, что:

вы можете иметь [Интерфейс Маркера] расширить интерфейс, к которому он применим, гарантируя, что все отмеченные типы также являются подтипами единственного интерфейса, к которому он применим.

Не можете ли вы также достичь этого с помощью аннотаций, используя мета-аннотацию @Inherited?

Ответ 1

Как можно ориентировать интерфейс маркера более точно?

Вы правы, что оба могут быть применены к любому типу. "Целесообразно более точно" автор означает, что вы можете добавить дополнительные ограничения, к которым могут применяться конкретные типы интерфейса маркера. Невозможно добавить те же точные ограничения для аннотаций: если аннотация ограничена ElementType.TYPE, она всегда может применяться ко всем типам.

В другой части 2-го пункта подробно описывается, как вы можете добавить эти ограничения. Если у вас есть интерфейс маркера, вы можете позволить ему расширить другой интерфейс (который автор называет единственным интерфейсом) следующим образом:

interface Marker extends Foo { }

Теперь маркер можно применять только к типам, которые реализуют Foo.

Не можете ли вы также достичь этого с помощью аннотаций, используя мета-аннотация @Inherited?

Нет, мета-аннотация @Inherited означает только, что любой подтип аннотированного класса будет обрабатываться так, как если бы он также имел ту же самую аннотацию. Он не налагает никаких ограничений на то, к каким типам может применяться аннотация.