Почему невозможно расширять аннотации в Java?

Я не понимаю, почему в аннотациях Java нет наследования, как классы Java. Я думаю, что это было бы очень полезно.

Например: я хочу знать, является ли данная аннотация валидатором. С наследованием я мог рефлексивно перемещаться по суперклассам, чтобы узнать, расширяет ли это аннотация ValidatorAnnotation. В противном случае, как я могу достичь этого?

Итак, может ли кто-нибудь дать мне повод для этого дизайнерского решения?

Ответ 1

О причине, по которой он не был спроектирован таким образом, вы можете найти ответ в FAQ по JSR 175 Design, где написано:

Почему вы не поддерживаете подтипы аннотаций (когда один тип аннотации расширяет другой)?

Это усложняет систему типов аннотаций и значительно усложняет написание "Конкретных инструментов".

...

"Специальные инструменты" - программы, которые запрашивают известные типы аннотаций произвольных внешних программ. Например, генераторы-заглушки попадают в эту категорию. Эти программы будут читать аннотированные классы, не загружая их в виртуальную машину, но будут загружать интерфейсы аннотаций.

Так что, да, я думаю, причина в том, что это просто ПОЦЕЛУЙ. В любом случае, кажется, что эта проблема (наряду со многими другими) рассматривается как часть JSR 308, и вы даже можете найти альтернативный компилятор с этой функциональностью, уже разработанной Матиасом Рикеном.

Ответ 2

Расширяемые аннотации эффективно добавили бремя определения и поддержки системы другого типа. И это будет довольно уникальная система типов, поэтому вы не можете просто применить парадигму типа OO.

Продумайте все проблемы, когда вы вводите полиморфизм и наследование в аннотацию (например, что происходит, когда суб-аннотация изменяет спецификации мета-аннотации, такие как сохранение?)

И все это добавило сложности для использования?

Вы хотите знать, принадлежит ли данная аннотация к категории?

Попробуйте следующее:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    String category();
}

@Category(category="validator")
public @interface MyFooBarValidator {

}

Как вы можете видеть, вы можете легко группировать и классифицировать аннотации без излишней боли, используя предоставленные средства.

Итак, KISS является причиной того, что на язык Java не вводится система типа мета-типа.

[p.s. редактировать]

Я использовал String просто для демонстрации и с учетом аннотации с открытым концом. Для вашего собственного проекта вы, очевидно, можете использовать перечисление типов категорий и указать несколько категорий ( "множественное наследование" ) для данной аннотации. Обратите внимание, что значения полностью фиктивные и только для демонстрационных целей:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    AnnotationCategory[] category();
}
public enum AnnotationCategory {
    GENERAL,
    SEMANTICS,
    VALIDATION,
    ETC
}

@Category(category={AnnotationCategory.GENERAL, AnnotationCategory.SEMANTICS})
public @interface FooBarAnnotation {

}

Ответ 3

В некотором смысле у вас уже есть это с аннотациями - meta Annotations. Если вы аннотируете аннотацию с метаинформацией, это во многом эквивалентно расширению дополнительного интерфейса. Аннотации - это интерфейсы, поэтому полиморфизм действительно не вступает в игру, и поскольку они носят статический характер, динамическая диспетчеризация времени выполнения не может быть.

В вашем примере валидатора вы можете просто добавить аннотацию к аннотированному типу и посмотреть, есть ли мета-аннотация для валидатора.

Единственный случай использования, я мог видеть, что наследование помогло бы, если бы вы хотели получить аннотацию по супер-типу, но это добавило бы целую сложность, потому что данный метод или тип могут иметь две такие аннотации на нем, что означает, что массив должен быть возвращен вместо одного объекта.

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

Ответ 4

Дизайнеры поддержки аннотаций Java сделали ряд "упрощений" в ущерб сообществу Java.

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

  • Только одна аннотация конкретного типа для каждого сайта. Это привело к совершенно ненужной схеме аннотации коллекции. @Validation и @Validations, @Image и @Images и т.д.

Второе исправляется в Java 8, но слишком поздно. Многие фреймворки были написаны на основе того, что было возможно на Java 5, и теперь эти бородавки API здесь, чтобы оставаться надолго.

Ответ 5

Одна вещь, о которой я мог подумать, - это возможность иметь несколько аннотаций. Таким образом, вы можете добавить валидатор и более конкретную аннотацию в одном месте. Но я мог ошибаться:)

Ответ 6

Никогда не думал об этом, но... кажется, что вы правы, нет никаких проблем с объектом наследования аннотаций (по крайней мере, я не вижу проблемы с ним).

В вашем примере с аннотацией "валидатор" вы можете использовать подход мета-аннотации. То есть вы применяете конкретную мета-аннотацию ко всему интерфейсу аннотации.

Ответ 7

Мне может быть на три года поздно ответить на этот вопрос, но я нашел это интересным, потому что я оказался в том же месте. Здесь я беру на себя это. Вы можете просматривать аннотации в виде Enums. Они предоставляют одностороннюю информацию - используют ее или теряют.

У меня была ситуация, когда я хотел смоделировать GET, POST, PUT и DELETE в веб-приложении. Мне так сильно хотелось иметь "супер" аннотацию, которая называлась "HTTP_METHOD". Позже рассвело на меня, что это не имеет значения. Ну, я должен был согласиться с использованием скрытого поля в форме HTML, чтобы идентифицировать DELETE и PUT (потому что POST и GET были доступны в любом случае).

На стороне сервера я искал скрытый параметр запроса с именем "_method". Если значение было PUT или DELETE, то оно перегружает соответствующий HTTP-запрос. Сказав это, неважно, нужно ли мне продлевать аннотацию, чтобы выполнить эту работу. Все аннотации выглядели одинаково, но на стороне сервера они обрабатывались по-разному.

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

Ответ 8

та же проблема, что и у меня. Нет, ты не можешь. Я сам "дисциплинировал", чтобы писать свойства в аннотациях, чтобы уважать некоторые стандарты, поэтому снаружи, когда вы получаете аннотацию, вы можете "обнюхать", какую аннотацию какого-то типа, это свойства, которые она имеет.