Статья написана на основе курса от компании Oracle "Learning the Java language", раздела "Annotations". Статья подойдет тем, кто встречался с аннотациями на практике и хочет углубить или освежить теоретические знания. Аннотации - это форма метаданных. Они предоставляют информацию о программе, при том сами частью программы не являются. Информация для компилятора. Могут использоваться компилятором для обнаружения ошибок и подавления предупреждений. Обработка во время компиляции и развертывания. Программа может создавать код, XML-файлы и т.п. на основе аннотаций. Обработка во время выполнения. Некоторые аннотации могут использоваться во время выполнения программы. Начинаются с @, могут включать элементы, которым присваиваются значения: Если такой элемент один, его имя можно опустить: Если таких элементов нет, можно опустить скобки. Можно использовать несколько аннотаций в одном объявлении: Аннотации могут быть повторяющимися. Аннотации применяются с объявлениями классов, полей и других элементов программы. Аннотации, использующиеся с типами, называются аннотациями типов. Примеры таких аннотаций: Создание экземпляра класса: Приведение к типу: Имплементация: Объявление бросаемых исключений: Описание аннотации напоминает описание интерфейса. Оно начинается с @Interface, а его элементы похожи на методы, которые могут иметь дефолтные значения. Допустим, в какой-то IT-компании тела всех классов начинаются с комментариев, содержащих важную информацию: Описание аннотации, которая заменит комментарии: Использование созданной аннотации: Замечание: для добавления аннотации в Javadocs нужно использовать @Documented: В Java есть аннотации, описанные заранее. Часть из них предоставляют информацию для компилятора, часть применяется к другим аннотациям. Располагаются в пакете java.lang. @Deprecated Помеченный этой аннотацией элемент устарел и больше не должен использоваться (это стоит отметить в Javadoc). При наличии такого элемента в программе компилятор сгенерирует предупреждение. @Override Информирует компилятор о том, что аннотируемый элемент должен переопределять элемент родительского класса. При некорректном переопределении компилятор сгенерирует ошибку. @SuppressWarnings Подавляет генерируемые компилятором предупреждения. Предупреждения делятся на непроверенные (unchecked) и устаревшие (deprecation). Первые возникают при использовании устаревшего кода, написанного до дженериков, вторые - при использовании кода, помеченного аннотацией @Deprecated. Можно подавить как одну категорию, так и обе сразу: @SafeVarargs Применяется к методу или конструктору и утверждает, что код не выполняет потенциально небезопасных операций с параметрами varargs. При использовании аннотации подавляются unchecked предупреждения, связанные с varargs. @FunctionalInterface Используется при описании функционального интерфейса. Подчеркивает, что это именно функциональный интерфейс. Располагаются в пакете java.lang.annotation. @Retention Указывает, сколько хранится отмеченная аннотация. RetentionPolicy.SOURCE. Отмеченная аннотация сохраняется только на уровне исходного кода и игнорируется компилятором. RetentionPolicy.CLASS. Сохраняется компилятором во время компиляции, но игнорируется JVM. RetentionPolicy.RUNTIME. Сохраняется JVM для использования во время выполнения программы. @Documented Указывает, что аннотация, должна быть задокументирована в Javadoc (по умолчанию аннотации не документируются). @Target Определяет права доступа аннотации (к каким элементам ее можно применять). В аннотации @Target указывается одно из следующих значений: ElementType.ANNOTATION_TYPE. Применяется к аннотации ElementType.CONSTRUCTOR. Применяется к конструктору. ElementType.FIELD. Применяется к полю или свойству. ElementType.LOCAL_VARIABLE. Применяется к локальной переменной. ElementType.METHOD. Применяется к методу. ElementType.PARAMETER. Применяется к параметру метода. ElementType.TYPE. Применяется к любому элементу класса. @Inherited Аннотация будет наследоваться дочерним классом (по умолчанию аннотации не наследуются). Применима только к описаниям классов. @Repeatable Указывает, что аннотация повторяющаяся. Аннотации, которые могут применяться к одному и тому же элементу более одного раза. Допустим, вам надо написать аннотацию, запускающую метод в заданное время или по определенному расписанию. В примере созданная аннотация @Schedule будет запускать метод каждый последний день месяца и каждую пятницу в 23:00. Для обеспечения обратной совместимости повторяющиеся аннотации хранятся в контейнере аннотаций, который автоматически генерируется java компилятором. Для генерации нужны следующие описания: Описание повторяющейся аннотации Аннотация должна быть помечена @Repeatable, в скобках указан тип контейнера аннотаций. Описание контейнера аннотаций Контейнер должен содержать массив повторяющихся аннотаций. Reflection API предоставляет методы для получения аннотаций. При получении повторяющихся аннотаций поведение методов, которые возвращают одну аннотацию (например, AnnotatedElement.getAnnotation(Class<T>)) не меняется. Если нужно вернуть более одной, то необходимо сначала получить контейнер. Таким образом устаревший код продолжает работать. Также, для получения повторяющихся аннотаций можно использовать методы Java SE 8 ('AnnotatedElement.getAnnotationsByType(Class)'). Для получения информации о всех методах, обратитесь к документации класса AnnotatedElement. Аннотации типов - аннотации, которые применяются вместе с типами. Везде, где вы видите тип, можно использовать эту аннотацию. Например, с оператором new, при приведении, при имплементации и при использовании throws. Для создания аннотации типов в @Target указываются следующие значения, либо одно из них: TYPE_PARAMETER, означает, что аннотацию можно применять к переменным типа (например, MyClass<T>). TYPE_USE, разрешает применение с любыми типами. Аннотации типов предназначены для улучшенного анализа программ и более строгой проверки типов. Например, @NonNull String str;. Java SE8 определяет аннотации типов, но не реализует. Вместо этого предлагается использовать сторонние фреймворки, реализующие их (Checker Framework).