1. Обзор
В этом уроке мы узнаем, как получить аннотации поля. Кроме того, мы объясним, как работает мета-аннотация удержания. После этого мы покажем разницу между двумя методами, которые возвращают аннотации поля.
2. Политика хранения аннотации
Во-первых, давайте посмотрим на аннотацию Retention .
Он определяет жизненный цикл аннотации. Эта мета-аннотация принимает атрибут RetentionPolicy
.
То есть атрибут определяет жизненный цикл ,
в котором аннотация видна:
RetentionPolicy.SOURCE —
виден только в исходном кодеRetentionPolicy.CLASS
— виден компилятору во время компиляции.RetentionPolicy.RUNTIME —
виден компилятору и среде выполнения.
Таким образом, только политика хранения RUNTIME
позволяет нам программно читать аннотацию .
3. Получите аннотации поля с помощью отражения
Теперь давайте создадим пример класса с аннотированным полем. Мы определим три аннотации, из которых во время выполнения видны только две.
Первая аннотация видна во время выполнения:
@Retention(RetentionPolicy.RUNTIME)
public @interface FirstAnnotation {
}
Второй имеет такое же удержание:
@Retention(RetentionPolicy.RUNTIME)
public @interface SecondAnnotation {
}
Наконец, давайте создадим третью аннотацию, видимую только в исходном коде:
@Retention(RetentionPolicy.SOURCE)
public @interface ThirdAnnotation {
}
Теперь давайте определим класс с полем classMember,
аннотированным всеми тремя нашими аннотациями:
public class ClassWithAnnotations {
@FirstAnnotation
@SecondAnnotation
@ThirdAnnotation
private String classMember;
}
После этого давайте получим все видимые аннотации во время выполнения. Мы будем использовать отражение Java , которое позволяет нам проверять атрибуты поля:
@Test
public void whenCallingGetDeclaredAnnotations_thenOnlyRuntimeAnnotationsAreAvailable() throws NoSuchFieldException {
Field classMemberField = ClassWithAnnotations.class.getDeclaredField("classMember");
Annotation[] annotations = classMemberField.getDeclaredAnnotations();
assertThat(annotations).hasSize(2);
}
В результате мы получили только две аннотации, доступные во время выполнения. Метод getDeclaredAnnotations
возвращает массив нулевой длины, если в поле нет аннотаций.
Мы можем прочитать аннотации поля суперкласса таким же образом: получить поле суперкласса и вызвать тот же метод getDeclaredAnnotations
.
4. Проверьте, аннотировано ли поле определенным типом
Давайте теперь посмотрим, как проверить, присутствует ли конкретная аннотация в поле. Класс Field
имеет метод isAnnotationPresent
, который возвращает значение true
, если в элементе присутствует аннотация для указанного типа. Давайте проверим это на нашем поле classMember
:
@Test
public void whenCallingIsAnnotationPresent_thenOnlyRuntimeAnnotationsAreAvailable() throws NoSuchFieldException {
Field classMemberField = ClassWithAnnotations.class.getDeclaredField("classMember");
assertThat(classMemberField.isAnnotationPresent(FirstAnnotation.class)).isTrue();
assertThat(classMemberField.isAnnotationPresent(SecondAnnotation.class)).isTrue();
assertThat(classMemberField.isAnnotationPresent(ThirdAnnotation.class)).isFalse();
}
Как и ожидалось, ThirdAnnotation
отсутствует, поскольку для метааннотации Retention
указана политика хранения SOURCE
.
5. Полевые
методы getAnnotations
и getDeclaredAnnnotations
Давайте теперь посмотрим на два метода, предоставляемые классом Field ,
getAnnotations
и getDeclaredAnnotations
. Согласно Javadoc, метод getDeclaredAnnotations
возвращает аннотации, непосредственно присутствующие в элементе . С другой стороны, Javadoc говорит для getAnnotations
, что он возвращает все аннотации, присутствующие в элементе .
Поле в классе содержит аннотации непосредственно над его определением. В результате наследования аннотаций вообще не происходит. Все аннотации должны быть определены вместе с определением поля. Из-за этого методы getAnnotations
и getDeclaredAnnotations
всегда возвращают один и тот же результат .
Покажем это на простом тесте:
@Test
public void whenCallingGetDeclaredAnnotationsOrGetAnnotations_thenSameAnnotationsAreReturned() throws NoSuchFieldException {
Field classMemberField = ClassWithAnnotations.class.getDeclaredField("classMember");
Annotation[] declaredAnnotations = classMemberField.getDeclaredAnnotations();
Annotation[] annotations = classMemberField.getAnnotations();
assertThat(declaredAnnotations).containsExactly(annotations);
}
Более того, в классе Field
мы можем обнаружить, что метод getAnnotations
вызывает метод getDeclaredAnnotations
:
@Override
public Annotation[] getAnnotations() {
return getDeclaredAnnotations();
}
6. Заключение
В этой короткой статье мы объяснили роль метааннотаций политики хранения в получении аннотаций. Затем мы показали, как читать аннотации поля. Наконец, мы доказали, что для поля не существует наследования аннотаций.
Как всегда, исходный код примера доступен на GitHub .