Аннотация Java

редактировать

В языке компьютерного программирования Java аннотация представляет собой синтаксическую форму метаданные, которые можно добавить в исходный код Java . Классы, методы, переменные, параметры и Пакеты Java могут быть аннотированы. Как и теги Javadoc, аннотации Java можно читать из исходных файлов. В отличие от тегов Javadoc, аннотации Java также могут быть встроены и считаны из файлов классов Java, сгенерированных компилятором Java. Это позволяет сохранять аннотации виртуальной машиной Java во время времени выполнения и читать через отражение. В Java можно создавать мета-аннотации из существующих.

Содержание
  • 1 История
  • 2 Встроенные аннотации
  • 3 Пример
    • 3.1 Встроенные аннотации
    • 3.2 Пользовательские аннотации
  • 4 Обработка
  • 5 Использование в естественных условиях
  • 6 См. Также
  • 7 Ссылки
  • 8 Внешние ссылки
История

Платформа Java имеет различные специальные механизмы аннотации - например, модификатор transientили тег @deprecatedjavadoc. Запрос на спецификацию Java JSR-175 представил в 2002 году средство аннотации общего назначения (также известное как метаданные) для Java Community Process ; он получил одобрение в сентябре 2004 г. Аннотации стали доступны на самом языке, начиная с версии 1.5 пакета Java Development Kit (JDK). Инструмент apt предоставил предварительный интерфейс для обработки аннотаций во время компиляции в JDK версии 1.5; JSR-269 формализовал это, и он был интегрирован в компилятор javac в версии 1.6.

Встроенные аннотации

Java определяет набор аннотаций, встроенных в язык. Из семи стандартных аннотаций три являются частью java.lang, а остальные четыре импортированы из java.lang.annotation.

Аннотации, применяемые к коду Java:

  • @Override- Проверяет, является ли метод переопределением. Вызывает ошибку компиляции , если метод не найден в одном из родительских классов или реализованных интерфейсах.
  • @Deprecated- помечает метод как устаревший. Вызывает предупреждение компиляции, если используется метод.
  • @SuppressWarnings- инструктирует компилятор подавлять предупреждения времени компиляции, указанные в параметрах аннотации.

Аннотации, применяемые к другим аннотациям (также известные как «Мета-аннотации»):

  • @Retention- указывает, как хранится отмеченная аннотация: только в коде, скомпилирована в класс или доступна во время выполнения посредством отражения.
  • @Documented- Отмечает другую аннотацию для включения в документацию.
  • @Target- Отмечает другую аннотацию, чтобы ограничить, к какому типу элементов Java эта аннотация может применяться.
  • @Inherited- Отмечает другую аннотацию как наследуется подклассам аннотированного класса (по умолчанию аннотации не наследуются подклассами).

Начиная с Java 7, в язык были добавлены три дополнительных аннотации.

  • @SafeVarargs- подавлять предупреждения для всех вызывающих методов или конструкторов с параметром generics varargs, начиная с Java 7.
  • @FunctionalInterface- Указывает, что объявление типа предназначено для функционального интерфейса, начиная с Java 8.
  • @Repeatable- указывает, что аннотация может применяться более одного раза к такое же объявление, начиная с Java 8.
Пример

Встроенные аннотации

Этот пример демонстрирует использование аннотации @Override. Он инструктирует компилятор проверить родительские классы на соответствие методов. В этом случае возникает ошибка, потому что метод gettype ()класса Cat фактически не переопределяет getType ()класса Animal, как это желательно, из-за несоответствующий регистр. Если аннотация @Overrideотсутствовала, в классе Cat был бы создан новый метод с именем gettype ().

общедоступный класс Animal {общедоступный void speak () {} общедоступный String getType () {return "Generic animal"; }} public class Cat extends Animal {@Override public void speak () {// Это хорошее переопределение. System.out.println ("Мяу."); } @Override public String gettype () {// Ошибка времени компиляции из-за опечатки: должно быть getType (), а не gettype (). return «Кошка»; }}

Пользовательские аннотации

Объявления типа аннотации аналогичны обычным объявлениям интерфейса. Ат-знак (@) предшествует ключевому слову интерфейса. Каждое объявление метода определяет элемент типа аннотации. Объявления методов не должны иметь никаких параметров или предложения throws. Типы возвращаемых данных ограничены примитивами , String, Class, enums, аннотациями и массивами предыдущих типов. Методы могут иметь значения по умолчанию.

// @Twizzle - это аннотация к методу toggle (). @Twizzle public void toggle () {} // Объявляет аннотацию Twizzle. public @interface Twizzle {}

Аннотации могут включать необязательный список пар ключ-значение:

// То же, что и: @Edible (value = true) @Edible (true) Item item = new Carrot (); public @interface Edible {логическое значение () по умолчанию false; } @Author (first = "Oompah", last = "Loompah") Book book = new Book (); public @interface Автор {String first (); Строка last (); }

Сами аннотации могут быть аннотированы, чтобы указать, где и когда они могут использоваться:

@Retention (RetentionPolicy.RUNTIME) // Сделайте эту аннотацию доступной во время выполнения через отражение. @Target ({ElementType.METHOD}) // Эта аннотация может применяться только к методам класса. public @interface Tweezable {}

Компилятор резервирует набор специальных аннотаций (включая @Deprecated, @Overrideи @SuppressWarnings) для синтаксических целей.

Аннотации часто используются фреймворками как способ удобного применения поведения к определяемым пользователем классам и методам, которые в противном случае должны быть объявлены во внешнем источнике (таком как файл конфигурации XML) или программно (с вызовами API). Следующее, например, представляет собой аннотированный класс данных JPA :

@Entity // Объявляет этот объектный компонент @Table (name = "people") // Сопоставляет bean-компонент с таблицей SQL "people "Открытый класс Person реализует Serializable {@Id // Сопоставьте его со столбцом первичного ключа. @GeneratedValue (strategy = GenerationType.AUTO) // База данных будет генерировать новые первичные ключи, а не мы. частный целочисленный идентификатор; @Column (length = 32) // Обрезать значения столбца до 32 символов. частное строковое имя; общедоступное целое число getId () {идентификатор возврата; } public void setId (Целочисленный идентификатор) {this.id = id; } public String getName () {возвращаемое имя; } public void setName (имя строки) {this.name = name; }}

Аннотации не являются вызовами методов и сами по себе ничего не делают. Вместо этого объект класса передается в реализацию JPA во время времени выполнения, которая затем извлекает аннотации для создания объектно-реляционного сопоставления.

Полный пример: приведено ниже:

com.annotation пакета; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Documented @Retention (RetentionPolicy.RUNTIME) @Target ({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE, ElementType.PACKAGE, ElementType.FIELD, ElementType_public @PublicType. enum Priority {LOW, MEDIUM, HIGH} String value (); String changedBy () default ""; String lastChangedBy () default ""; Priority priority () по умолчанию Priority.MEDIUM; String createdBy () default «Джеймс Гослинг»; Строка lastChanged () по умолчанию «2011-07-08»; }
com.annotation пакета; public @interface UnderConstruction {String owner () default "Патрик Нотон"; Строковое значение () по умолчанию «Объект в разработке.»; String createdBy () по умолчанию «Майк Шеридан»; Строка lastChanged () по умолчанию «2011-07-08»; }
пакет com.validators; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.validator.Validator; import javax.faces.validator.ValidatorException; import com.annotation.UnderConstruction; import com.annotation.Unfinished; import com.annotation.Unfinished.Priority; import com.util.Util; @UnderConstruction (owner = "Jon Doe") открытый класс DateValidator реализует Validator {public void validate (контекст FacesContext, компонент UIComponent, значение объекта) бросает ValidatorException {String date = (String) value; String errorLabel = "Пожалуйста, введите действительную дату."; если (! component.getAttributes (). isEmpty ()) {errorLabel = (String) component.getAttributes (). get ("errordisplayval"); } if (! Util.validateAGivenDate (date)) {@Unfinished (changedBy = "Steve", value = "добавлять сообщение в контекст или нет, подтвердить", priority = Priority.HIGH) FacesMessage message = new FacesMessage (); message.setSeverity (FacesMessage.SEVERITY_ERROR); message.setSummary (errorLabel); message.setDetail (errorLabel); выбросить новое исключение ValidatorException (сообщение); }}}
Обработка

Когда исходный код Java компилируется, аннотации могут обрабатываться подключаемыми модулями компилятора, называемыми процессорами аннотаций. Процессоры могут создавать информационные сообщения или создавать дополнительные исходные файлы или ресурсы Java, которые, в свою очередь, могут компилироваться и обрабатываться. Однако обработчики аннотаций не могут изменять сам аннотированный код. (Модификации кода могут быть реализованы с использованием методов, выходящих за рамки Спецификации языка Java.) Компилятор Java условно сохраняет метаданные аннотации в файлах классов, если аннотация имеет RetentionPolicyиз CLASSили РАБОТА. Позже JVM или другие программы могут искать метаданные, чтобы определить, как взаимодействовать с элементами программы или изменить их поведение.

Помимо обработки аннотации с помощью процессора аннотации, программист на Java может написать свой собственный код, который использует отражения для обработки аннотации. Java SE 5 поддерживает новый интерфейс, определенный в пакете java.lang.reflect. Этот пакет содержит интерфейс под названием AnnotatedElement, который реализуется классами отражения Java, включая Class, Constructor, Field, Methodи Пакет. Реализации этого интерфейса используются для представления аннотированного элемента программы, выполняющейся в настоящее время на виртуальной машине Java. Этот интерфейс позволяет рефлексивно читать аннотации.

Интерфейс AnnotatedElementобеспечивает доступ к аннотациям с сохранением RUNTIME. Этот доступ обеспечивается методами getAnnotation, getAnnotationsи isAnnotationPresent. Поскольку типы аннотаций компилируются и хранятся в файлах с байтовым кодом, как и классы, аннотации, возвращаемые этими методами, могут запрашиваться так же, как любой обычный объект Java. Полный пример обработки аннотации приведен ниже:

import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; // Это аннотация, которая будет обработана // По умолчанию для Target - все элементы Java // Измените политику хранения на RUNTIME (по умолчанию - CLASS) @Retention (RetentionPolicy.RUNTIME) public @interface TypeHeader {// Значение по умолчанию, указанное для атрибута разработчика String developer () по умолчанию "Неизвестно"; Строка lastModified (); Строка teamMembers (); int valueOfLife (); }
// Это аннотация, применяемая к классу @TypeHeader (developer = "Bob Bee", lastModified = "2013-02-12", teamMembers = {"Ann", "Dan", "Fran"}, meanOfLife = 42) public class SetCustomAnnotation {// Содержимое класса находится здесь}
// Это пример кода, который обрабатывает аннотацию import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; открытый класс UseCustomAnnotation {общедоступный статический void main (String args) {Class classObject = SetCustomAnnotation.class; readAnnotation (classObject); } static void readAnnotation (элемент AnnotatedElement) {попробуйте {System.out.println ("Значения элемента аннотации: \ n"); if (element.isAnnotationPresent (TypeHeader.class)) {// getAnnotation возвращает тип аннотации Аннотация singleAnnotation = element.getAnnotation (TypeHeader.class); Заголовок TypeHeader = (TypeHeader) singleAnnotation; System.out.println ("Разработчик:" + header.developer ()); System.out.println ("Последнее изменение:" + header.lastModified ()); // teamMembers возвращается как String System.out.print ("Team members:"); для (член строки: header.teamMembers ()) System.out.print (член + ","); System.out.print ("\ п"); System.out.println («Смысл жизни:» + header.meaningOfLife ()); }} catch (исключение исключения) {exception.printStackTrace (); }}}
Использование в естественных условиях

Исследователи изучили использование аннотаций Java в 1094 известных проектах Java с открытым исходным кодом, размещенных на GitHub. Они обнаружили, что аннотации активно поддерживаются, при этом многие аннотации добавляются, но также изменяются или удаляются из-за ошибок в типе или значениях аннотации. В целом, это исследование показывает, что существует небольшая, но значимая взаимосвязь между использованием аннотаций и вероятностью ошибок кода: Java-код с аннотациями, как правило, менее подвержен ошибкам.

См. Также
Ссылки
Внешние ссылки
Последняя правка сделана 2021-05-24 03:57:37
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте