Аннотация(@Annotation) — форма метаданных, предоставляющая данные о программе, которая не является частью самой программы. Аннотации не имеют прямого влияния на работу кода, они аннотируют его и представляют из себя лишь мета информацию.
package java.lang.annotation;
содержание
Аннотации используются в трех случаях:
- @Retention(RetentionPolicy.CLASS) — Аннотации должны быть записаны в файле класса компилятором, но не обязательно должен быть сохранен JVM во время выполнения. Это поведение по умолчанию.
- @Retention(RetentionPolicy.SOURCE) — Аннотации могут быть использованы компилятором для обнаружения ошибок или подавления предупреждений например @SuppressWarnings;
- @Retention(RetentionPolicy.RUNTIME) — Аннотации должны быть записаны в файле класса компилятором и сохранятся в VM во время выполнения, так что они могут быть прочитаны с помощью рефлексии;
Аннотированы могут быть пакеты, классы, методы, переменные и параметры.
Как создать Аннотацию в java
Аннотации очень схожи с интерфейсами, соответственно как и интерфейсы они могут быть только public. Модификатор доступа так же как и с интерфейсами можно не писать.
|
1 2 3 4 5 6 |
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface SomeName { String name() default "Leo"; int value(); } |
Символ @ — указывает компилятору, что объявлена аннотация. Методы, объявленные в аннотации ведут себя скорее как поля.
@interface — указывает на то, что это аннотация
default — говорит про то, что метод по умолчанию будет возвращать определённое значение.
Конфигурация Аннотации
Аннотация без конфигурирования может применяться к любым элементам: классам, методам, полям, атрибутами так далее…
Аннотация @Target позволит нам ограничить Scope ее применения.
@Target(ElementType.PACKAGE) — только для пакетов;
@Target(ElementType.TYPE) — только для классов;
@Target(ElementType.CONSTRUCTOR) — только для конструкторов;
@Target(ElementType.METHOD) — только для методов;
@Target(ElementType.FIELD) — только для атрибутов(переменных) класса;
@Target(ElementType.PARAMATER) — только для параметров метода;
@Target(ElementType.LOCAL_VARIABLE) — только для локальных переменных.
В случае если вы хотите, что бы ваша аннотация использовалась больше чем для одного типа параметров, то можно указать @Target следующим образом:
|
1 |
@Target({ ElementType.PARAMETER, ElementType.LOCAL_VARIABLE }) |
аннотация можно будет использовать только для параметров метода и для локальных переменных
Как использовать свою аннотацию
|
1 2 3 4 5 |
//Аннотирование метода @SomeName(name = "Пример аннотации", value = 100) public static void someMethod() { // some code... } |
Наша аннотация @someName это практически интерфейс который ничего не реализует, поэтому мы должны указать что будет происходить с аннотированным кодом.
Аннотация это всего лишь маркер который выделяет что-то, и по этому маркеру мы можем легко найти фрагмент кода и что нибудь с ним сделать.
Реализация
Теперь реализуем всем известный framework JUnit
|
1 2 3 4 5 |
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Test { Class expected(); } |
Теперь мы должны для нашей аннотации написать класс анализатор. Этот класс будет анализировать наши аннотации и выполнять некоторые действия, связанные с аннотируемыми параметрами.
Наш анализатор будет использовать Reflection для доступа к аннотируемым данным:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public class TestAnnotationAnalyzer { public void analyz(Class<?> clazz) throws Exception { Method[] methods = clazz.getMethods(); int pass = 0; int fail = 0; for (Method method : methods) { if (method.isAnnotationPresent(Test.class)) { // Получаем доступ к атрибутам Test test = method.getAnnotation(Test.class); Class expected = test.expected(); try { method.invoke(null); pass++; } catch (Exception e) { if (Exception.class != expected) { fail++; } else { pass++; } } } } } } |
В строке 10 мы получаем доступ к атрибуту аннотации и дальше в строке 11 получаем значение атрибута аннотации, в нашем случае это значение типа Class так как expected — это ожидаемая ошибка и мы будем получать exception.
Ну и в строке 16 мы проверяем ожидаемый Exception с полученным.
Внимание! Аннотации появились в языке Java с появлением версии 1.5. В версиях ниже 1.5 нет возможности использовать аннотации.
Материалы:
https://docs.oracle.com/javase/tutorial/java/annotations/