Аннотации Java - Википедия - Java annotation

в Язык программирования Java, аннотация это форма синтаксического метаданные что можно добавить в Java исходный код.[1] Классы, методы, переменные, параметры и Пакеты Java могут быть аннотированы. Нравиться Javadoc теги, аннотации Java могут быть прочитаны из исходных файлов. В отличие от Javadoc теги, аннотации Java также могут быть встроены и прочитаны из Файлы классов Java генерируется Компилятор Java. Это позволяет сохранять аннотации Виртуальная машина Java в время выполнения и читайте через отражение.[2] Возможно создание метааннотаций из существующих в Java.[3]

История

В Платформа Java имеет различные для этого случая механизмы аннотации - например, преходящий модификатор, или @deprecated тег javadoc. В Запрос спецификации Java JSR-175 представил аннотацию общего назначения (также известную как метаданные) объект Процесс сообщества Java в 2002; он получил одобрение в сентябре 2004 г.[4]Аннотации стали доступны на самом языке начиная с версии 1.5 Комплект для разработки Java (JDK). В подходящий инструмент предоставил предварительный интерфейс для обработки аннотаций во время компиляции в JDK версии 1.5; JSR-269 формализовал это, и он стал интегрирован в javac компилятор в версии 1.6.

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

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

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

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

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

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

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

Пример

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

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

общественный учебный класс Животное {    общественный пустота разговаривать() {    }    общественный Нить getType() {        возвращаться «Родовое животное»;    }}общественный учебный класс Кот расширяет Животное {    @Override    общественный пустота разговаривать() { // Это хорошее переопределение.        Система.из.println("Мяу.");    }    @Override    общественный Нить gettype() { // Ошибка времени компиляции из-за опечатки: должно быть getType (), а не gettype ().        возвращаться "Кот";    }}

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

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

  // @Twizzle - это аннотация к методу toggle ().  @Twizzle  общественный пустота переключать() {  }  // Объявляет аннотацию Twizzle.  общественный @интерфейс Twizzle {  }

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

  // То же, что и: @Edible (value = true)  @Edible(истинный)  Элемент элемент = новый Морковь();  общественный @интерфейс Съедобный {      логический ценить() дефолт ложный;  }  @ Автор(первый = "Умпа", последний = "Лумпа")  Книга книга = новый Книга();  общественный @интерфейс Автор {      Нить первый();      Нить последний();  }

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

  @Удержание(Политика удержания.ВРЕМЯ) // Делаем эту аннотацию доступной во время выполнения через отражение.  @Цель({ElementType.МЕТОД})       // Эта аннотация может применяться только к методам класса.  общественный @интерфейс Пинцет {  }

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

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

@Юридическое лицо                                             // Объявляет объектный компонент@Стол(имя = "люди")                             // Сопоставляет bean-компонент с таблицей SQL "people"общественный учебный класс Человек орудия Сериализуемый {    @Идентификатор                                             // Сопоставьте это с столбцом первичного ключа.    @GeneratedValue(стратегия = GenerationType.АВТО) // База данных будет генерировать новые первичные ключи, а не нас.    частный Целое число я бы;    @Столбец(длина = 32)                            // Обрезать значения столбца до 32 символов.    частный Нить имя;    общественный Целое число getId() {        возвращаться я бы;    }    общественный пустота установить идентификатор(Целое число я бы) {        это.я бы = я бы;    }    общественный Нить getName() {        возвращаться имя;    }    общественный пустота Имя набора(Нить имя) {        это.имя = имя;    }}

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

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

упаковка com.annotation;импорт java.lang.annotation.Documented;импорт java.lang.annotation.ElementType;импорт java.lang.annotation.Inherited;импорт java.lang.annotation.Retention;импорт java.lang.annotation.RetentionPolicy;импорт java.lang.annotation.Target;@ Документированный@Удержание(Политика удержания.ВРЕМЯ)@Цель({ElementType.ТИП,ElementType.МЕТОД,         ElementType.КОНСТРУКТОР,ElementType.ANNOTATION_TYPE,         ElementType.УПАКОВКА,ElementType.ПОЛЕ,ElementType.LOCAL_VARIABLE})@Inheritedобщественный @интерфейс Незаконченный {    общественный перечислить Приоритет { НИЗКИЙ, СРЕДНИЙ, ВЫСОКО }    Нить ценить();    Нить[] изменено() дефолт "";    Нить[] lastChangedBy() дефолт "";    Приоритет приоритет() дефолт Приоритет.СРЕДНИЙ;    Нить сделано() дефолт "Джеймс Гослинг";    Нить lastChanged() дефолт "2011-07-08";}
упаковка com.annotation;общественный @интерфейс В разработке {    Нить владелец() дефолт "Патрик Нотон";    Нить ценить() дефолт «Объект в стадии строительства».;    Нить сделано() дефолт "Майк Шеридан";    Нить lastChanged() дефолт "2011-07-08";}
упаковка com.validators;импорт javax.faces.application.FacesMessage;импорт javax.faces.component.UIComponent;импорт javax.faces.context.FacesContext;импорт javax.faces.validator.Validator;импорт javax.faces.validator.ValidatorException;импорт com.annotation.UnderConstruction;импорт com.annotation.Unfinished;импорт com.annotation.Unfinished.Priority;импорт com.util.Util;@В разработке(владелец="Джон Доу")общественный учебный класс DateValidator орудия Валидатор {	    общественный пустота подтверждать(FacesContext контекст, UIComponent компонент, Объект ценить)        бросает ValidatorException {        Нить Дата = (Нить) ценить;        Нить errorLabel = "Пожалуйста, введите правильную дату.";        если (!компонент.getAttributes().пусто()) {            errorLabel = (Нить) компонент.getAttributes().получать("errordisplayval");        }        если (!Util.validateAGivenDate(Дата)) {            @ Незаконченный(изменено = "Стив",                ценить = "добавлять сообщение в контекст или нет, подтвердить",                приоритет = Приоритет.ВЫСОКО            )            FacesMessage сообщение = новый FacesMessage();            сообщение.setSeverity(FacesMessage.SEVERITY_ERROR);            сообщение.setSummary(errorLabel);            сообщение.setDetail(errorLabel);            бросать новый ValidatorException(сообщение);        }    }}

Обработка

Когда исходный код Java компилируется, аннотации могут обрабатываться надстройками компилятора, называемыми обработчиками аннотаций. Процессоры могут создавать информационные сообщения или создавать дополнительные исходные файлы или ресурсы Java, которые, в свою очередь, могут компилироваться и обрабатываться. Однако обработчики аннотаций не могут изменять сам аннотированный код. (Модификации кода могут быть реализованы с использованием методов, выходящих за рамки Спецификации языка Java.) Компилятор Java условно сохраняет метаданные аннотации в файлах классов, если аннотация имеет Политика удержания из УЧЕБНЫЙ КЛАСС или же ВРЕМЯ. Позже JVM или другие программы могут искать метаданные, чтобы определить, как взаимодействовать с элементами программы или изменить их поведение.

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

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

импорт java.lang.annotation.Retention;импорт java.lang.annotation.RetentionPolicy;// Это аннотация для обработки// По умолчанию для Target - все элементы Java// Измените политику хранения на RUNTIME (по умолчанию CLASS)@Удержание(Политика удержания.ВРЕМЯ)общественный @интерфейс Тип Заголовок {    // Значение по умолчанию указано для атрибута разработчика    Нить разработчик() дефолт "Неизвестный";    Нить Последнее изменение();    Нить [] Члены команды();    int Смысл жизни();}
// Это аннотация, применяемая к классу@TypeHeader(разработчик = "Боб Би",    Последнее изменение = "2013-02-12",    Члены команды = { "Анна", "Дэн", "Фрэн" },    Смысл жизни = 42)общественный учебный класс SetCustomAnnotation {    // Содержимое класса идет сюда}
// Это пример кода, который обрабатывает аннотациюимпорт java.lang.annotation.Annotation;импорт java.lang.reflect.AnnotatedElement;общественный учебный класс UseCustomAnnotation {    общественный статический пустота главный(Нить [] аргументы) {        Учебный класс<SetCustomAnnotation> classObject = SetCustomAnnotation.учебный класс;        readAnnotation(classObject);    }    статический пустота readAnnotation(AnnotatedElement элемент) {        пытаться {            Система.из.println(«Значения элемента аннотации:  n»);            если (элемент.isAnnotationPresent(Тип Заголовок.учебный класс)) {                // getAnnotation возвращает тип аннотации                Аннотации singleAnnotation =                         элемент.getAnnotation(Тип Заголовок.учебный класс);                Тип Заголовок заголовок = (Тип Заголовок) singleAnnotation;                Система.из.println("Разработчик:" + заголовок.разработчик());                Система.из.println("Последнее изменение: " + заголовок.Последнее изменение());                // teamMembers возвращается как String []                Система.из.Распечатать("Члены команды: ");                за (Нить член : заголовок.Члены команды())                    Система.из.Распечатать(член + ", ");                Система.из.Распечатать(" п");                Система.из.println("Смысл жизни: "+ заголовок.Смысл жизни());            }        } ловить (Исключение исключение) {            исключение.printStackTrace();        }    }}

Использование в дикой природе

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

Смотрите также

Рекомендации

  1. ^ "Аннотации". Sun Microsystems. Архивировано из оригинал на 2011-09-25. Получено 2011-09-30..
  2. ^ Sun Microsystems (2005). Спецификация языка Java (TM) (3-е изд.). Prentice Hall. ISBN  0-321-24678-0..
  3. ^ Не бойтесь Обасанджо (2007). "СРАВНЕНИЕ ЯЗЫКА ПРОГРАММИРОВАНИЯ C # MICROSOFT С ЯЗЫКОМ ПРОГРАММИРОВАНИЯ JAVA SUN MICROSYSTEMS: Аннотации метаданных". Не бойтесь Обасанджо. Архивировано из оригинал в 2012-09-19. Получено 2012-09-20.
  4. ^ Трус, Дэнни (2006-11-02). "JSR 175: средство метаданных для языка программирования JavaTM". Процесс сообщества Java. Получено 2008-03-05.
  5. ^ «Предопределенные типы аннотаций». Корпорация Oracle. Получено 2016-12-17.
  6. ^ «Встроенные аннотации: стандартные аннотации». Получено 2016-12-17.
  7. ^ Юй Чжунсин; Бай, Ченган; Сейнтюрье, Лайонел; Монперрус, Мартин (2019). «Описание использования, развития и влияния аннотаций Java на практике». IEEE Transactions по разработке программного обеспечения. arXiv:1805.01965. Дои:10.1109 / TSE.2019.2910516.

внешняя ссылка