Как получить аннотацию над аннотацией

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

Это метод, который я определил

@ApiTest
public void add() {
}

Это аннотация, которую я определил.

@ValueName("hello word")
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ApiTest {

}
////////////////////////////////////////////////////////
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ValueName {
  String value() default "";
}

Результат всегда возвращает null, когда я пытаюсь получить @ValueName

Class<?> testApi = Class.forName("com.huawei.netty.TestApi");
    Method add = testApi.getMethod("add", null);
    ApiTest apiTest = add.getDeclaredAnnotation(ApiTest.class);
    ValueName valueName = apiTest.getClass().getDeclaredAnnotation(ValueName.class);
    if (valueName != null) {
      System.out.println(valueName.annotationType());
    }

Но таким образом можно получить

Class<?> apiTest = Class.forName("com.huawei.netty.ApiTest");
    ValueName valueName = apiTest.getDeclaredAnnotation(ValueName.class);
    if (valueName != null) {
      System.out.println(valueName.value());
    }

Могу ли я узнать, почему это так?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
130
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы должны использовать Annotation#annotationType() для получения класса экземпляра аннотации, а не Object#getClass(). Последний метод не возвращает класс, который вы думаете. Попробуйте следующее:

MetaAnnotation.java

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface MetaAnnotation {

    String value();

}

CustomAnnotation.java

@MetaAnnotation("Hello, World!")
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CustomAnnotation {}

Main.java

@CustomAnnotation
public final class Main {

    public static void main(String[] args) {
        CustomAnnotation ca = Main.class.getAnnotation(CustomAnnotation.class);
        MetaAnnotation   ma = ca.annotationType().getAnnotation(MetaAnnotation.class);

        System.out.println("CustomAnnotation#getClass()       = " + ca.getClass());
        System.out.println("CustomAnnotation#annotationType() = " + ca.annotationType());
        System.out.println("MetaAnnotation#value()            = " + ma.value());
    }

}

Когда я запускаю вышеприведенное с помощью OpenJDK 12.0.1, я получаю следующий вывод:

CustomAnnotation#getClass()       = class com.sun.proxy.$Proxy1
CustomAnnotation#annotationType() = interface CustomAnnotation
MetaAnnotation#value()            = Hello, World!

Как видите, класс аннотации экземпляр является прокси-классом, который не будет иметь аннотацию, которую вы запрашиваете.

Другие вопросы по теме

Создание экземпляра класса данных Kotlin через отражение
Как вызвать DynamicMethod в DynamicMethod
Как получить все методы решения Visual Studio?
Как установить свойства объекта и его значение, если этот объект является свойством объекта, который находится внутри списка с использованием отражений
Как выполнить универсальный метод, установив двойной общий метод с использованием отражения
Почему объявлены поля, включая $change и serialVersionUID
Десериализовать объект JSON в конкретный экземпляр, созданный на лету во время выполнения, по строковому имени класса
JsonConvert.DeserializeObject выдает исключение при десериализации JSON с шестнадцатеричным значением в свойство sbyte
Используя С# Reflection, как получить свойства объекта и их значения, если этот объект является свойством объекта, который находится внутри списка
Почему ArrayList.class.isInstance(ArrayList.class) возвращает false?