Есть ли что-то вроде наследования аннотаций в Java? - PullRequest
100 голосов
/ 14 октября 2011

Я изучаю аннотации и дошел до того, что некоторые аннотации, кажется, имеют иерархию среди них.

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

@Target(value = {ElementType.TYPE})
public @interface Move extends Page{
 String method1();
 String method2();
}

И это будет обычная аннотация:

@Target(value = {ElementType.TYPE})
public @interface Page{
 String method3();
}

В приведенном выше примере я ожидаю, что Move наследует method3, но я получаю предупреждение о том, что extends недопустимы с аннотациями. Я пытался, чтобы Аннотация расширяла общую базу, но это не работает. Это вообще возможно или это просто проблема дизайна?

Ответы [ 3 ]

66 голосов
/ 14 октября 2011

К сожалению, нет. Очевидно, это как-то связано с программами, которые читают аннотации в классе, не загружая их полностью. См. Почему невозможно расширить аннотации в Java?

Однако типы наследуют аннотации своего суперкласса, если эти аннотации @Inherited.

Кроме того, если вам не нужны эти методы для взаимодействия, вы можете просто сложить аннотации для вашего класса:

@Move
@Page
public class myAwesomeClass {}

Есть ли какая-то причина, которая не будет работать для вас?

53 голосов
/ 03 сентября 2013

Вы можете аннотировать свою аннотацию базовой аннотацией вместо наследования.Это используется в Spring Framework .

Чтобы привести пример

@Target(value = {ElementType.ANNOTATION_TYPE})
public @interface Vehicle {
}

@Target(value = {ElementType.TYPE})
@Vehicle
public @interface Car {
}

@Car
class Foo {
}

Вы можете проверить, аннотирован ли класс с помощью Vehicle, используя Spring.AnnotationUtils :

Vehicle vehicleAnnotation = AnnotationUtils.findAnnotation (Foo.class, Vehicle.class);
boolean isAnnotated = vehicleAnnotation != null;

Этот метод реализован следующим образом:

public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
    return findAnnotation(clazz, annotationType, new HashSet<Annotation>());
}

@SuppressWarnings("unchecked")
private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, Set<Annotation> visited) {
    try {
        Annotation[] anns = clazz.getDeclaredAnnotations();
        for (Annotation ann : anns) {
            if (ann.annotationType() == annotationType) {
                return (A) ann;
            }
        }
        for (Annotation ann : anns) {
            if (!isInJavaLangAnnotationPackage(ann) && visited.add(ann)) {
                A annotation = findAnnotation(ann.annotationType(), annotationType, visited);
                if (annotation != null) {
                    return annotation;
                }
            }
        }
    }
    catch (Exception ex) {
        handleIntrospectionFailure(clazz, ex);
        return null;
    }

    for (Class<?> ifc : clazz.getInterfaces()) {
        A annotation = findAnnotation(ifc, annotationType, visited);
        if (annotation != null) {
            return annotation;
        }
    }

    Class<?> superclass = clazz.getSuperclass();
    if (superclass == null || Object.class == superclass) {
        return null;
    }
    return findAnnotation(superclass, annotationType, visited);
}

AnnotationUtils также содержит дополнительные методы для поиска аннотаций к методам и другим аннотированным элементам.Класс Spring также достаточно мощен для поиска по мостовым методам, прокси и другим угловым случаям, особенно в Spring.

5 голосов
/ 30 октября 2014

В дополнение к Григорийскому ответу на аннотирующие аннотации.

Вы можете проверить, например, методы для содержания аннотации @Qualifier (или аннотации, аннотированной @Qualifier) ​​этим циклом:

for (Annotation a : method.getAnnotations()) {
    if (a.annotationType().isAnnotationPresent(Qualifier.class)) {
        System.out.println("found @Qualifier annotation");//found annotation having Qualifier annotation itself
    }
}

Что вы в основном делаете, так это чтобы все аннотации присутствовали в методе, а из этих аннотаций вы получали их типы и проверяли эти типы, если они аннотированы @Qualifier. Для того, чтобы это работало, ваша аннотация должна быть включена для Target.Annotation_type.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...