2011-10-13 11 views
66

私はアノテーションを探究しており、いくつかのアノテーションには階層構造があるように見えます。Javaに注釈継承のようなものがありますか?

私は、注釈を使用してカードの背景にコードを生成しています。異なるカードタイプ(したがって異なるコードと注釈)がありますが、名前のような共通の要素があります。

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

そして、これは一般的な注釈のようになります。私は移動が法3を継承するために期待するが、私は、注釈と有効でない拡張警告ことわざを取得し、上記の例で

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

。注釈を共通の基盤に拡張しようとしていたが、それは機能しません。それは可能なのか、それとも単なる設計上の問題なのでしょうか?

+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です。

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

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

をこのメソッドは次のように実装されて:あなたは、クラスがSpring's AnnotationUtilsを使用してVehicleでアノテートされているかどうかを確認することができます例に

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

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

@Car 
class Foo { 
} 

を与えること

追加のメソッドも含まれていますメソッドやその他の注釈付き要素の注釈を検索するためのものです。 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

注釈アノテーションのグリゴイの答えに加えて。

このループによって@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の答えとどう違うのですか? –

関連する問題