В языке программирования компьютера Java , аннотации являются формой синтаксических метаданных , которые могут быть добавлены в Java исходного код . [1] Классы , методы , переменные , параметры и пакеты Java могут быть аннотированы. Как и теги Javadoc , аннотации Java можно читать из исходных файлов. В отличие от тегов Javadoc , аннотации Java также могут быть встроены и считаны из файлов классов Java, созданных компилятором Java . Это позволяет виртуальной машине Java сохранять аннотации ввремя выполнения и читать через отражение . [2] В Java можно создавать метааннотации из существующих. [3]
История [ править ]
Платформа Java имеет различные специальные механизмы аннотации, например transient
модификатор или @deprecated
тег javadoc. Спецификация Java Request JSR-175 представил общее назначение аннотацию (также известную как метаданные ) объект в рамки Java Community Process в 2002 году; он получил одобрение в сентябре 2004 года. [4]
Аннотации стали доступны на самом языке, начиная с версии 1.5 Java Development Kit (JDK). apt
Инструмент , при условии , временный интерфейс для компиляции обработки аннотаций в JDK версии 1.5; JSR-269 формализовал это, и он был интегрирован в javac. компилятор в версии 1.6.
Встроенные аннотации [ править ]
Java определяет набор аннотаций, встроенных в язык. Из семи стандартных аннотаций три являются частью java.lang , а остальные четыре импортированы из java.lang.annotation. [5] [6]
Аннотации, примененные к 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
аннотация отсутствовала, gettype()
в классе Cat был бы создан новый метод имени .
общественный класс Animal { public void speak () { } общедоступная строка getType () { return " Обычное животное" ; } }public class Cat extends Animal { @Override public void speak () { // Это хорошее переопределение. Система . из . println ( "Мяу." ); } @Override public String gettype () { // Ошибка времени компиляции из-за опечатки: должно быть getType (), а не gettype (). return "Кошка" ; } }
Пользовательские аннотации [ править ]
Объявления типов аннотаций аналогичны объявлениям обычных интерфейсов. Знак at (@) предшествует ключевому слову интерфейса . Каждое объявление метода определяет элемент типа аннотации. Объявления методов не должны иметь никаких параметров или предложения throws. Типы возвращаемых значений ограничены примитивами , String , Class, перечислениями , аннотациями и массивами предыдущих типов. У методов могут быть значения по умолчанию .
// @Twizzle - это аннотация к методу toggle (). @Twizzle public void toggle () { } // Объявляет аннотацию Twizzle. общественный @interface твизлы { }
Аннотации могут включать необязательный список пар ключ-значение:
// То же, что и: @Edible (value = true) @Edible ( true ) Item item = new Carrot (); общедоступный @interface Edible { логическое значение () по умолчанию false ; } @Author ( first = "Oompah" , last = "Loompah" ) Book book = new Book (); public @interface Автор { String first (); Строка last (); }
Сами аннотации могут быть аннотированы, чтобы указать, где и когда их можно использовать:
@Retention ( RetentionPolicy . RUNTIME ) // Сделайте эту аннотацию доступной во время выполнения через отражение. @Target ({ ElementType . METHOD }) // Эта аннотация может применяться только к методам класса. общественного @interface Tweezable { }
Составитель оставляет за собой набор специальных аннотаций ( в том числе @Deprecated
, @Override
и @SuppressWarnings
) для синтаксических целей.
Аннотации часто используются фреймворками как способ удобного применения поведения к определяемым пользователем классам и методам, которые в противном случае должны быть объявлены во внешнем источнике (например, в файле конфигурации XML) или программно (с вызовами API). Вот, например, аннотированный класс данных JPA :
@Entity // Объявляет объектный bean-компонент @Table ( name = "people" ) // Сопоставляет bean-компонент с таблицей SQL. Открытый класс "people" Person реализует Serializable { @Id // Сопоставляет это со столбцом первичного ключа. @GeneratedValue ( strategy = GenerationType . AUTO ) // База данных будет генерировать новые первичные ключи, а не мы. частный целочисленный идентификатор ; @Column ( length = 32 ) // Обрезать значения столбца до 32 символов. частное строковое имя ; общедоступное целое число getId () { идентификатор возврата ; } public void setId ( Целочисленный идентификатор ) { this . id = id ; } общедоступная строка getName () { возвращаемое имя ; } public void setName ( String name ) { 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 . ТИП , ElementType . МЕТОД , ElementType . КОНСТРУКТОР , ElementType . ANNOTATION_TYPE , ElementType . ПАКЕТ , ElementType . Область техники , ElementType . LOCAL_VARIABLE }) @Inheritedpublic @interface Unfinished { public enum Priority { LOW , MEDIUM , HIGH } String value (); String [] changedBy () по умолчанию "" ; String [] lastChangedBy () по умолчанию "" ; Priority priority () приоритет по умолчанию . СРЕДНИЙ ; String createdBy () default «Джеймс Гослинг» ; Строка lastChanged () по умолчанию «2011-07-08» ; }
пакет com.annotation ;общественного @interface строящихся { Строка владельца () по умолчанию «Патрик Нотон» ; Строковое значение () по умолчанию «Объект в разработке». ; String createdBy () default «Майк Шеридан» ; Строка 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 = "Пожалуйста, введите действительную дату." ; if ( ! component . getAttributes (). isEmpty ()) { errorLabel = ( String ) компонент . getAttributes (). получить ( "errordisplayval" ); } if ( ! Util . validateAGivenDate ( date )) { @Unfinished ( changedBy = "Steve" , value = "добавлять сообщение в контекст или нет, подтвердить" , priority = Priority . HIGH ) FacesMessage message = new FacesMessage (); сообщение . setSeverity ( FacesMessage . SEVERITY_ERROR ); сообщение . setSummary ( errorLabel); сообщение . setDetail ( errorLabel ); выбросить новое исключение ValidatorException ( сообщение ); } } }
Обработка [ править ]
Когда исходный код Java компилируется, аннотации могут обрабатываться подключаемыми модулями компилятора, называемыми обработчиками аннотаций. Процессоры могут создавать информационные сообщения или создавать дополнительные исходные файлы или ресурсы Java, которые, в свою очередь, могут компилироваться и обрабатываться. Однако обработчики аннотаций не могут изменять сам аннотированный код. (Модификации кода могут быть реализованы с использованием методов за пределами спецификации языка Java.) Компилятор Java условно хранит метаданные аннотаций в файлах классов, если в аннотации есть RetentionPolicy
из CLASS
или RUNTIME
. Позже JVM или другие программы могут искать метаданные, чтобы определить, как взаимодействовать с элементами программы или изменить их поведение.
Помимо обработки аннотации с помощью процессора аннотации, программист на Java может написать свой собственный код, который использует отражения для обработки аннотации. Java SE 5 поддерживает новый интерфейс, определенный в java.lang.reflect
пакете. Этот пакет содержит интерфейс , который называется AnnotatedElement
, реализуемый классами отражения Java , включая Class
, Constructor
, Field
, Method
, и Package
. Реализации этого интерфейса используются для представления аннотированного элемента программы, выполняющейся в настоящее время на виртуальной машине Java. Этот интерфейс позволяет рефлексивно читать аннотации.
AnnotatedElement
Интерфейс обеспечивает доступ к аннотациям , имеющих RUNTIME
задержку. Этот доступ обеспечивается getAnnotation
, getAnnotations
и isAnnotationPresent
методами. Поскольку типы аннотаций компилируются и хранятся в файлах с байтовым кодом точно так же, как классы, аннотации, возвращаемые этими методами, могут запрашиваться так же, как любой обычный объект Java. Полный пример обработки аннотации представлен ниже:
import java.lang.annotation.Retention ; import java.lang.annotation.RetentionPolicy ;// Это аннотаций для обработки // По умолчанию для Target это все Java Элементы политики удержания // Изменения в RUNTIME ( по умолчанию CLASS) @Retention ( RetentionPolicy . RUNTIME ) публичное @interface TypeHeader { // Значение по умолчанию указано для атрибута разработчиков String developer () по умолчанию "Неизвестно" ; Строка lastModified (); Строка [] teamMembers (); int valueOfLife (); }
// Это аннотация, применяемая к классу @TypeHeader ( developer = "Bob Bee" , lastModified = "2013-02-12" , teamMembers = { "Ann" , "Dan" , "Fran" }, что означаетOfLife = 42 )public class SetCustomAnnotation { // Содержимое класса находится здесь }
// Это пример кода, который обрабатывает аннотацию import java.lang.annotation.Annotation ; import java.lang.reflect.AnnotatedElement ;открытый класс UseCustomAnnotation { public static void main ( String [] args ) { Class < SetCustomAnnotation > classObject = SetCustomAnnotation . класс ; readAnnotation ( classObject ); } static void readAnnotation ( элемент AnnotatedElement ) { попробуйте { System . из . println ( "Значения элементов аннотации: \ n" ); if ( element . isAnnotationPresent ( TypeHeader . class )) { // getAnnotation возвращает тип аннотации Аннотация singleAnnotation = element . getAnnotation ( TypeHeader . класс ); Заголовок TypeHeader = ( TypeHeader ) singleAnnotation ; Система . из . println ( "Разработчик:" + заголовок . Разработчик ()); Система . из . println ( "Последнее изменение:" + заголовок . lastModified ()); // teamMembers возвращается как String [] System . из . print ( "Члены команды:" ); for ( String member : header . teamMembers ()) System . из . печать ( член + "," ); Система . из . печать ( "\ п" ); Система . из . println ( «Смысл жизни:» + заголовок . MeaningOfLife ()); } } catch ( исключение исключение ) { исключение . printStackTrace (); } } }
Использование в дикой природе [ править ]
Исследователи изучили использование аннотаций Java в 1094 известных Java-проектах с открытым исходным кодом, размещенных на GitHub. Они обнаружили, что аннотации активно поддерживаются, при этом многие аннотации добавляются, но также изменяются или удаляются из-за ошибок в типе или значениях аннотации. В целом, это исследование показывает, что существует небольшая, но значимая взаимосвязь между использованием аннотаций и вероятностью ошибок кода: Java-код с аннотациями, как правило, менее подвержен ошибкам. [7]
См. Также [ править ]
- JSR 250: Общие аннотации для платформы Java
- Атрибуты интерфейса командной строки
- Программирование на Java
- Виртуальная машина Java
- Модельно-управляемая архитектура
- Декораторы Python , вдохновленные аннотациями Java, имеют похожий синтаксис.
Ссылки [ править ]
- ^ «Аннотации» . Sun Microsystems . Архивировано из оригинала на 2011-09-25 . Проверено 30 сентября 2011 ..
- ^ Sun Microsystems (2005). Спецификация языка Java (TM) (3-е изд.). Прентис Холл . ISBN 0-321-24678-0..
- ^ Dare Обасанджо (2007). "СРАВНЕНИЕ ЯЗЫКА ПРОГРАММИРОВАНИЯ C # MICROSOFT С ЯЗЫКОМ ПРОГРАММИРОВАНИЯ JAVA SUN MICROSYSTEMS: Аннотации метаданных" . Не бойтесь Обасанджо. Архивировано из оригинала на 2012-09-19 . Проверено 20 сентября 2012 .
- ^ Трус, Дэнни (2006-11-02). «JSR 175: средство метаданных для языка программирования JavaTM» . Процесс сообщества Java . Проверено 5 марта 2008 .
- ^ «Предопределенные типы аннотаций» . Корпорация Oracle . Проверено 17 декабря 2016 .
- ^ «Встроенные аннотации: стандартные аннотации» . Проверено 17 декабря 2016 .
- ^ Ю, Чжунсин; Бай, Ченган; Сейнтюрье, Лайонел; Монперрус, Мартин (2019). «Описание использования, развития и влияния аннотаций Java на практике» . IEEE Transactions по разработке программного обеспечения . arXiv : 1805.01965 . DOI : 10.1109 / TSE.2019.2910516 .
Внешние ссылки [ править ]
- Введение в аннотации Java 6 на сайте Sun Developer Network
- Введение в аннотации Java. Автор М.М. Ислам Чистый.
- Введение в аннотации Java 5.0 от Джой Кристи
- Аннотации Java Джона Ханта
- Пользовательские аннотации в Java
- Объяснение аннотаций Java
- Понимание аннотаций в Java