java中的注释继承是否有类似内容?

时间:2011-10-13 23:16:41

标签: java inheritance annotations

我正在探索注释,并且发现某些注释似乎在它们之间具有层次结构。

我正在使用注释在后台为卡片生成代码。存在不同的卡类型(因此不同的代码和注释)但是在它们之间存在某些共同的元素,如名称。

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

这将是常见的注释:

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

在上面的示例中,我希望Move继承方法3但是我收到一条警告,说扩展对注释无效。我试图让Annotation扩展一个共同的基础,但这不起作用。这甚至可能还是只是一个设计问题?

4 个答案:

答案 0 :(得分:66)

不幸的是,没有。显然它与程序有关,这些程序读取类上的注释而不会一直加载它们。见Why is not possible to extend annotations in Java?

但是,如果这些注释为@Inherited,则类型会继承其超类的注释。

此外,除非您需要这些方法进行交互,否则您只需在类上堆叠注释:

@Move
@Page
public class myAwesomeClass {}

有什么理由对你不起作用吗?

答案 1 :(得分:51)

您可以使用基本注释而不是继承来注释注释。这是used in Spring framework

举个例子

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

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

@Car
class Foo {
}

然后,您可以使用Spring's AnnotationUtils检查某个类是否使用Vehicle注释:

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中遇到的案例。

答案 2 :(得分:5)

除了Grygoriys注释注释的答案。

您可以查看,例如通过此循环包含@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才能使其正常工作。

答案 3 :(得分:1)

签出https://github.com/blindpirate/annotation-magic,这是我在遇到相同问题时开发的库。

@interface Animal {
    boolean fluffy() default false;

    String name() default "";
}

@Extends(Animal.class)
@Animal(fluffy = true)
@interface Pet {
    String name();
}

@Extends(Pet.class)
@interface Cat {
    @AliasFor("name")
    String value();
}

@Extends(Pet.class)
@interface Dog {
    String name();
}

@interface Rat {
    @AliasFor(target = Animal.class, value = "name")
    String value();
}

@Cat("Tom")
class MyClass {
    @Dog(name = "Spike")
    @Rat("Jerry")
    public void foo() {
    }
}

        Pet petAnnotation = AnnotationMagic.getOneAnnotationOnClassOrNull(MyClass.class, Pet.class);
        assertEquals("Tom", petAnnotation.name());
        assertTrue(AnnotationMagic.instanceOf(petAnnotation, Animal.class));

        Animal animalAnnotation = AnnotationMagic.getOneAnnotationOnClassOrNull(MyClass.class, Animal.class);
        assertTrue(animalAnnotation.fluffy());

        Method fooMethod = MyClass.class.getMethod("foo");
        List<Animal> animalAnnotations = AnnotationMagic.getAnnotationsOnMethod(fooMethod, Animal.class);
        assertEquals(Arrays.asList("Spike", "Jerry"), animalAnnotations.stream().map(Animal::name).collect(toList()));