Среди интерфейсов выделяется особая группа, которая не объявляет никаких методов. Пример такого интерфейса –
Serializable. Такие интерфейсы добавляют классу некую семантику, которая позже используется либо с помощью рефлексии (и
instanceof), либо вообще не программно, а как информация для разработчиков и инструментов разработки. Это
маркерные интерфейсы. Маркерный интерфейс представляет
метаинформацию класса.
Начиная с Java 1.5 в языке появился новый вид типов –
аннотации. Они берут на себя и
расширяют возможности маркерного интерфейса:
1. Можно применять аннотацию не только к классу или интерфейсу, но почти к чему угодно: к пакетам, к методам, их параметрам, переменным. Полный список представлен в перечислении
ElementType;
2. Аннотация может нести данные в своих
элементах3. Аннотация может не присутствовать в рантайме, или даже остаться только в исходнике, не попав в байткод вовсе. Определяется ее
RetentionPolicy;
4. Можно сделать аннотацию не наследуемой, просто не помечая ее
@Inherited;
5. И конечно же, синтаксис. Примененная аннотация с первого взгляда отличается от настоящих интерфейсов.
Joshua Block в
главе 37 Effective Java выделяет два преимущества маркерных интерфейсов перед аннотациями
на этапе компиляции:
1. Можно требовать использование только маркированного параметра, так как маркерный интерфейс – это еще и тип;
2. Можно сузить применяемость маркера к только определенным типам, сделав интерфейс их наследником.
Возвращаясь к вопросу, ключевое слово
@interface объявляет аннотацию,
interface – интерфейс.
В результате компиляции в
.class-файле аннотация превращается в интерфейс-наследник
java.lang.annotation.Annotation, помеченный флагом
ACC_ANNOTATION. Элементы превращаются в абстрактные методы. Этим объясняется синтаксис объявления. Специфичные для аннотаций атрибуты описаны в
JVMS 4.7.16-4.7.22.
К слову, конструкции вида
@something в javadoc называются
тегами. Они выглядят похоже на аннотации, также представляют метаинформацию для документации, но технически не имеют с ними ничего общего.