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