2011-10-13 21 views
66

我在研究註釋,並且發現一些註釋似乎在它們之間具有層次結構。有沒有像java中的Annotation Inheritance的東西?

我使用註釋在卡的背景中生成代碼。存在不同的卡片類型(因此不同的代碼和註釋),但是其中有一些像名稱一樣常見的元素。

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

,這將是通用註解:

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

在上面的例子中我希望移動繼承方法3,但我得到一個警告說,延長不與註釋有效。我試圖讓一個Annotation擴展一個共同的基礎,但這不起作用。這甚至可能或只是一個設計問題?

+0

註解繼承似乎是基於註釋創建DSL的必備工具。不支持註釋繼承的這種遺憾。 – Ceki

+0

我同意,看起來很自然。特別是在瞭解Java的繼承之後,你會期望它適用於所有事情。 – javydreamercsw

回答

49

不幸的是,沒有。顯然它與程序有關,它們在一個類上讀取註釋而不會一直加載它們。請參閱Why is not possible to extend annotations in Java?

但是,如果這些註釋是@Inherited,則類型會繼承其超類的註釋。

而且,除非你需要這些方法來進行交互,你可能只是堆在你的類註釋:

@Move 
@Page 
public class myAwesomeClass {} 

是有一些原因,不會爲你工作?

+1

這就是我的想法,但我試圖簡化事情。也許把普通的一個應用到一個抽象類中會有訣竅... – javydreamercsw

+1

是的,那看起來也很聰明。祝你好運! – andronikus

33

您可以使用基本註釋而不是繼承註釋註釋。這是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 AnnotationUtilsVehicle

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

+11

請包括如何處理此類註釋的說明。 –

+1

您可以使用Spring的AnnotationUtils.findAnnotation(..),請參閱:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/AnnotationUtils.html#findAnnotation-java .lang.Class-java.lang.Class- – rgrebski

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以使其正常工作。

+0

這與Grygoriy的回答有什麼不同? –