2017-09-07 63 views
0

私は​​とSuperClassとアノテーションDocAnnotationを持っています。すべてのクラスの注釈を​​とSuperClassから取得するには、SubClass.foo()への電話が必要です。@継承されたアノテーションは継承されていません

スーパークラス

package Code 

import Annotations.DocAnnotation; 
import java.util.Arrays; 

@DocAnnotation("Super Annotation") 
public class SuperClass { 

    public void foo() { 
     System.out.println(Arrays.toString(this.getClass().getAnnotations())); 
     System.out.println(Arrays.toString(this.getClass().getDeclaredAnnotations())); 
    } 
} 

サブクラス

package Code; 

import Annotations.DocAnnotation; 

@DocAnnotation("Sub Annotation") 
public class SubClass extends SuperClass{ 
} 

DocAnnotation私は"Super Annotation""Sub Annotation"の両方を見ることを期待ではなく、私SubClass.fooを実行

package Annotations; 

import java.lang.annotation.Inherited; 
import java.lang.annotation.Repeatable; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 

@Inherited 
@Retention(RetentionPolicy.RUNTIME) 
@Repeatable(DocAnnotations.class) 
public @interface DocAnnotation { 
    String value(); 
} 

:クラスは、次のように定義されていますのみを表示0。 @inheritedが何をしているのか誤解していますか、間違って何かしていますか?


編集:

注釈を追加した後@DocAnnotation("Super Annotation")​​(つまりSuperClassと同じものをだ)、それは実際に​​での使用のために1回、2回現れ、一度SuperClassでの使用のために!今私は何かを誤解していることをほとんど確信しています...

答えて

2

これは意図した動作であると思われる、あるいは少なくともそれがこの方法(doc)を動作するように指定します:

[...]ユーザーがクラス宣言に注釈型を照会する場合は、とクラス宣言にはこのタイプの注釈がありません、クラスのスーパークラスは自動的に注釈タイプを照会されます。すなわち

​​が既に@DocAnnotationで注釈されているので、スーパークラスが照会されていません。

さらに詳しく調べると、特に注釈タイプが含まれていることを実験した後で、動作が少し変わっているようです。私はこれを示す次の例(link)を思い付いた:

import java.lang.annotation.*; 
import java.util.*; 

@Inherited 
@Repeatable(Container.class) 
@Retention(RetentionPolicy.RUNTIME) 
@interface Ann { 
    String value(); 
} 

@Inherited 
@Retention(RetentionPolicy.RUNTIME) 
@interface Container { 
    Ann[] value(); 
} 

// Basic case. Result is that 
// only @Ann("2") is present on 
// ExhibitASub. 
@Ann("1") 
class ExhibitASuper { 
} 
@Ann("2") 
class ExhibitASub extends ExhibitASuper { 
} 

// Because this case results in the 
// @Container being present on ExhibitBSuper, 
// rather than @Ann, all three annotations 
// end up appearing on ExhibitBSub. 
@Ann("1") 
@Ann("2") 
class ExhibitBSuper { 
} 
@Ann("3") 
class ExhibitBSub extends ExhibitBSuper { 
} 

// Similar to the preceding case, by 
// forcing the use of @Container, both 
// annotations are present on ExhibitCSub. 
@Container(@Ann("1")) 
class ExhibitCSuper { 
} 
@Ann("2") 
class ExhibitCSub extends ExhibitCSuper { 
} 

// Yet when we force both to use @Container, 
// only @Container(@Ann("2")) is present on 
// ExhibitDSub. 
@Container(@Ann("1")) 
class ExhibitDSuper { 
} 
@Container(@Ann("2")) 
class ExhibitDSub extends ExhibitDSuper { 
} 

class Main { 
    public static void main(String[] args) { 
     for (Class<?> cls : Arrays.asList(ExhibitASub.class, 
              ExhibitBSub.class, 
              ExhibitCSub.class, 
              ExhibitDSub.class)) { 
      System.out.printf("%s:%n", cls); 
      for (Annotation ann : cls.getAnnotations()) { 
       System.out.printf(" %s%n", ann); 
      } 

      System.out.println(); 
     } 
    } 
} 

以下の通りとなっている出力:BおよびCのために、我々はスーパークラスに注釈の両方を見ること

class ExhibitASub: 
    @Ann(value=2) 

class ExhibitBSub: 
    @Container(value=[@Ann(value=1), @Ann(value=2)]) 
    @Ann(value=3) 

class ExhibitCSub: 
    @Container(value=[@Ann(value=1)]) 
    @Ann(value=2) 

class ExhibitDSub: 
    @Container(value=[@Ann(value=2)]) 

注サブクラス。おそらく、これは、(厳密には)スーパークラスに存在するアノテーションが、サブクラスに存在するアノテーションと異なるタイプであるためであると思われる。 Dの場合、両方のクラスがコンテナタイプを使用するため、サブクラスアノテーションのみを表示することに戻ります。含む注釈型を使用して

は、明示的にいくつかの例の回避策かもしれないが、それが理由の場合の一般的な解決策ではありませんD.

これはかなり望ましくないと思われるので、私はこの明日のためにバグレポートを提出することがあります。 @Inheritedの前に@Repeatableが存在するため、このような状況が発生しなかった以前のバージョンの動作である可能性があります。

+0

私はコンテナの注釈を完全に忘れてしまった!それは本当にループのために私を投げていた...私が記述している動作が可能かどうか知っていますか?私は直接サブクラスが拡張するすべてのクラスを照会することができましたが、それは醜いコードのようです。より良い解決策はありますか? – bendl

+0

私はそうは思わない。別の解決策は、注釈を完全に放棄してインタフェースを使用することです。あなたのケースではそれが良いかどうかは本当に言えませんが、クラスに注釈を付けるのでうまくいく可能性があります。 – Radiodef

+0

私は注釈に固執しなければならないと思うが、ありがとう!あなたがバグレポートを提出することになったら、ここにリンクを投稿してください。私は、オラクルがこの振る舞いも期待しているかどうかを知ることに興味があります。 – bendl

2

この注釈は間違っています。 javadocには、明確に記載されています。

アノテーションタイプが自動的に継承されることを示します。継承されたメタアノテーションがアノテーション型宣言に存在し、ユーザーがクラス宣言でアノテーション型を照会し、クラス宣言にこの型の注釈がない場合、そのクラスのスーパークラスは自動的に注釈型に対して照会されます。言い換えれば

:あなたはサブクラスを照会する場合は、が注釈を付けされているスーパークラスを見つけるだろう。しかし、この事はであり、ではなく、の相続であり、 "OOの意味で"である。 アノテーションの両方を表示する場合は、クラスをクラス継承ツリーに手動でチェックするコードを記述する必要があります。

関連する問題