Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

В языке программирования компьютера 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-коду:

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

  • @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, имеют похожий синтаксис.

Ссылки [ править ]

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