Аннотации java зачем нужны

Как работают аннотации в Java и зачем они нужны

Java-аннотации используются для предоставления метаданных для вашего Java-кода. Будучи метаданными, напрямую не влияют на выполнение кода, хотя некоторые типы могут фактически использоваться для этой цели.

Цели

Обычно используются для следующих целей:

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

Можно использовать во время сборки, когда вы создаете свой программный проект. Процесс включает в себя:

  • генерацию исходного кода;
  • компиляцию исходного кода;
  • генерацию файлов XML (например, дескрипторов развертывания);
  • упаковку скомпилированного кода и файлов в файл JAR и т. д.

Сборка программного обеспечения обычно выполняется с помощью инструмента автоматической сборки, такого как Apache Ant или Apache Maven. Инструменты могут сканировать ваш код на предмет конкретных аннотаций и генерировать исходный код или другие файлы на основе их.

Доступ через отражение Java

Обычно аннотации отсутствуют в вашем коде после компиляции. Однако можно определить свои собственные. Затем к ним получить доступ через Java Reflection и использовать, чтобы давать инструкции для вашей программы или какого-либо стороннего API.

Основы

Символ @ сообщает компилятору, что это аннотация. Имя, следующее за символом @, является ее именем. В приведенном выше примере имя – Entity.

Элементы

@Entity(tableName = "vehicles")

Аннотация в этом примере содержит единственный элемент с именем tableName со значением, установленным для транспортных средств. Элементы заключены в круглые скобки после названия. Аннотации без элементов не нуждаются в скобках.

@Entity(tableName = "vehicles", primaryKey = "id")

Размещение

@Entity public class Vehicle

Аннотация начинается с символа @, за которым следует имя. В этом случае имя – Entity.

@Entity public class Vehicle < @Persistent protected String vehicleName = null; @Getter public String getVehicleName() < return this.vehicleName; >public void setVehicleName(@Optional vehicleName) < this.vehicleName = vehicleName; >public List addVehicleNameToList(List names) < @Optional List localNames = names; if(localNames == null) < localNames = new ArrayList(); >localNames.add(getVehicleName()); return localNames; > >

Примечания не имеют конкретного значения в Java.

Встроенные

Java поставляется с тремя встроенными аннотациями, которые используются для предоставления инструкций компилятора Java:

@Deprecated

@Deprecated public class MyComponent

Использование @Deprecated над объявлением класса помечает класс как устаревший.

Вы также можете использовать @Deprecated выше для описания методов и полей, чтобы пометить метод или поле как устаревшие.

@Deprecated /** @deprecated Use MyNewComponent instead. */ public class MyComponent

@Override

@Override используется над методами, которые переопределяют методы в суперклассе. Если метод не соответствует методу в суперклассе, компилятор выдаст вам ошибку.

@Override не обязательна для переопределения метода в суперклассе. В случае, если кто-то изменил имя переопределенного метода в суперклассе, ваш метод подкласса больше не будет переопределять его. Без @Override вы бы не узнали об этом. С @Override компилятор скажет вам, что метод в подклассе не переопределяет ни один метод в суперклассе.

public class MySuperClass < public void doTheThing() < System.out.println("Do the thing"); >> public class MySubClass extends MySuperClass < @Override public void doTheThing() < System.out.println("Do it differently"); >>

В случае, если метод doTheThing() в MySuperClass изменяет подпись, так, что тот же метод в подклассе больше не переопределяет его, компилятор выдаст ошибку.

@SuppressWarnings

@SuppressWarnings заставляет компилятор подавлять предупреждения для данного метода. Например, если метод вызывает устаревший метод или выполняет небезопасное приведение типа, компилятор может сгенерировать предупреждение. Вы можете подавить эти предупреждения, пометив метод, содержащий код, @SuppressWarnings.

@SuppressWarnings public void methodWithWarning()

Создание собственных

Можно создавать свои собственные (пользовательские) аннотации. Определяются в своем собственном файле, как класс или интерфейс Java.

Пример

В этом примере определяется аннотация MyAnnotation, которая имеет четыре элемента. Обратите внимание на ключевое слово @interface. Это сигнализирует компилятору Java, что это определение примечаний.

Обратите внимание, что каждый элемент определяется аналогично определению метода в интерфейсе. У него есть тип данных и имя. Вы можете использовать все примитивные типы данных, а также массивы в качестве типа данных элемента. Сложные объекты в качестве типа данных не применяются.

@MyAnnotation( value=»123″, name=»Jakob», age=37, newNames= ) public class MyClass

Как видите, я должен указать значения для всех элементов аннотации MyAnnotation.

Значения элемента по умолчанию

@MyAnnotation( name=»Jakob», age=37, newNames= ) public class MyClass

Обратите внимание, что элемент значения больше не присутствует.

@Retention

import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation

@Retention(RetentionPolicy.RUNTIME)

Это то, что сигнализирует компилятору Java и JVM, что аннотация должна быть доступна через отражение во время выполнения.

Класс RetentionPolicy содержит еще два значения, которые вы можете использовать:

  1. RetentionPolicy.CLASS означает, что примечание хранится в файле .class, но недоступна во время выполнения. Это политика хранения по умолчанию, если вы вообще не указали политику хранения.
  2. RetentionPolicy.SOURCE означает, что примечание доступно только в исходном коде, а не в файлах .class и не во время выполнения. Если создаете свои собственные аннотации для использования с инструментами сборки, которые сканируют код, можете использовать эту политику хранения. Таким образом, файлы .class не загрязняются без необходимости.

@Target

import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target() public @interface MyAnnotation

В этом примере показана аннотация, которую можно использовать только для аннотирования методов.

Класс ElementType содержит следующие возможные цели:

  • ElementType.ANNOTATION_TYPE;
  • ElementType.CONSTRUCTOR;
  • ElementType.FIELD;
  • ElementType.LOCAL_VARIABLE;
  • ElementType.METHOD;
  • ElementType.PACKAGE;
  • ElementType.PARAMETER;
  • ElementType.TYPE.

Большинство из них самоочевидны, но некоторые нет. Поэтому я объясню цели, которые не очевидны.

Цель ANNOTATION_TYPE означает определение. Таким образом, аннотация может использоваться только для аннотирования других примечаний. Как @Target и @Retention.

Цель TYPE означает любой тип. Тип – это класс, интерфейс, перечисление или аннотация.

@Inherited

java.lang.annotation.Inherited @Inherited public @interface MyAnnotation
@MyAnnotation public class MySuperClass
public class MySubClass extends MySuperClass

В этом примере класс MySubClass наследует аннотацию @MyAnnotation, потому что MySubClass наследуется от MySuperClass, а MySuperClass имеет @MyAnnotation.

@Documented

import java.lang.annotation.Documented; @Documented public @interface MyAnnotation
@MyAnnotation public class MySuperClass

При генерации JavaDoc для класса MySuperClass @MyAnnotation теперь включается в JavaDoc.

Источник

Аннотации в JAVA: обзор синтаксиса и создание собственных

Статья ориентирована больше на новичков, или тех, кто еще не работал с данным механизмом в языке. Я постараюсь рассказать, что это такое, зачем они нужны, и как можно самому создавать удобные для себя аннотации.

Аннотации представляют из себя дескрипторы, включаемые в текст программы, и используются для хранения метаданных программного кода, необходимых на разных этапах жизненного цикла программы.
Информация, хранимая в аннотациях, может использоваться соответствующими обработчиками для создания необходимых вспомогательных файлов или для маркировки классов, полей и т.д.

Синтаксис

Аннотация задается описанием соответствующего интерфейса.
Например так:

import java.lang.annotation.*; @Target(value=ElementType.FIELD) @Retention(value= RetentionPolicy.RUNTIME) public @interface Name

Как видно из примера выше, аннотация определяется описанием с ключевым словом interface и может включать в себя несколько полей, которые можно задать как обязательными, так и не обязательными. В последнем случае подставляется default значение поля.
Также из примера видно, что саму аннотацию можно пометить несколькими аннотациями.
Разберемся для начала, чем можно пометить собственную аннотацию, и зачем.

Аннотация @Retention позволяет указать жизненный цикл аннотации: будет она присутствовать только в исходном коде, в скомпилированном файле, или она будет также видна и в процессе выполнения. Выбор нужного типа зависит от того, как вы хотите использовать аннотацию, например, генерировать что-то побочное из исходных кодов, или в процессе выполнения стучаться к классу через reflection.

Аннотация @Target указывает, что именно мы можем пометить этой аннотацией, это может быть поле, метод, тип и т.д.

Аннотация @Documentedуказывает, что помеченная таким образом аннотация должна быть добавлена в javadoc поля/метода и т.д.
Например, класс, помеченный аннотацией без @Documented, будет выглядеть так:

public class TestClass extends java.lang.Object

А если в описание аннотации добавить @Documented, получим:

@ControlledObject(name="name") public class TestClass extends java.lang.Object

Аннотация @Inherited помечает аннотацию, которая будет унаследована потомком класса, отмеченного такой аннотацией.
Сделаем для примера пару аннотаций и пометим ими класс.

@Inherited @interface PublicAnnotate < >@interface PrivateAnnotate < >@PublicAnnotate @PrivateAnnotate class ParentClass < >class ChildClass extends ParentClass

Класс ChildClass унаследует от родительского класса только аннотацию PublicAnnotate.

Пример своей аннотации.

Попробуем теперь написать рабочий пример с использованием аннотаций.
Представим себе, что у нас есть какой-то самодельный проект, который на вход получает класс, специально заанотированный, чтобы проект мог управлять жизненным циклом объектов этого класса, и пусть там будут аннотации StartObject, StopObject для описания методов класса, и ControlledObject для описания самого класса. Последней аннотации дадим еще поле name, путь там хранится якобы имя для поиска.
Аннотации будут выглядеть так:

@Target(value=ElementType.METHOD) @Retention(value= RetentionPolicy.RUNTIME) public @interface StartObject < >@Target(value=ElementType.METHOD) @Retention(value= RetentionPolicy.RUNTIME) public @interface StopObject < >@Target(value=ElementType.TYPE) @Retention(value= RetentionPolicy.RUNTIME) public @interface ControlledObject

Напишем модуль, проверяющий подходит ли класс для загрузки в наш гипотетический проект или нет.
Сперва определим сам проверяемый класс.

@ControlledObject(name="biscuits") public class Cookies < @StartObject public void createCookie()< //бизнес логика >@StopObject public void stopCookie() < //бизнес логика >>

Для того, чтобы работать с классом, сначала необходимо загрузить класс в контекст приложения. Используем:
Class cl = Class.forName(«org.annotate.test.classes.Cookies»);
Далее, через механизм reflection мы получаем доступ к полям и аннотациям класса.
Проверим наличие аннотированных методов в классе и аннотации на самом классе:

if(!cl.isAnnotationPresent(ControlledObject.class)) < System.err.println("no annotation"); >else < System.out.println("class annotated ; name - " + cl.getAnnotation(ControlledObject.class)); >boolean hasStart=false; boolean hasStop=false; Method[] method = cl.getMethods(); for(Method md: method) < if(md.isAnnotationPresent(StartObject.class)) if(md.isAnnotationPresent(StopObject.class)) if(hasStart && hasStop) > System.out.println("Start annotaton - " + hasStart + "; Stop annotation - " + hasStop ); 

Запустив, на выходе мы получим:
Start annotaton — true; Stop annotation — true.
Если попробовать убрать одну из аннотаций, то вывод сообщит о несоответствии требованиям.

Итог

Надеюсь, мне удалось показать, что аннотации предоставляют широкие возможности для работы с кодом программ, и имеет смысл не только пользоваться стандартными аннотациями языка, но и облегчать себе жизнь, создавая аннотации под свои нужды.

Подробнее ознакомиться с данным механизмом могу порекомендовать в книге «Java 2. Библиотека профессионала, том 2. Тонкости программирования» Кей С. Хорстманна, Гари Корнелла, или на сайте oracle, где так же есть подробные туториалы.

Источник

Читайте также:  Содержит ли строка подстроку kotlin
Оцените статью