2011-01-20 10 views
91

GuiceのAOPを使ってメソッド呼び出しをインターセプトしています。私のクラスはインターフェースを実装しているので、Guiceが適切なメソッドを選択できるようにインターフェースメソッドにアノテートしたいと思います。またJavaクラスが実装されたインタフェースからアノテーションを継承しないのはなぜですか?

(注)このメタ注釈 のみスーパークラスから を継承するために注釈を引き起こすこと;:注釈型がInherited注釈実装するクラスでアノテートされている場合でもの継承Javaのドキュメントに記載されているように注釈を継承しません。 実装されたインターフェイスの注釈 は効果がありません。

この理由は何ですか?オブジェクトのクラスが実行時に実装するすべてのインタフェースを知ることは難しいことではないので、この決定の背後には十分な理由があるはずです。

答えて

109

私は、そうしなければ、多重継承の問題が発生するという理由があると言いたいと思います。

例:

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) @Inherited 
public @interface Baz { String value(); } 

public interface Foo{ 
    @Baz("baz") void doStuff(); 
} 

public interface Bar{ 
    @Baz("phleem") void doStuff(); 
} 

public class Flipp{ 
    @Baz("flopp") public void doStuff(){} 
} 

public class MyClass extends Flipp implements Foo, Bar{} 

私はこれを行う場合:

MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value() 

結果がために何が起こっているのか? 'baz'、 'phleem'または 'flopp'?


この理由から、インターフェイス上の注釈はほとんど役に立ちません。 @InheritedためJavadocから

+8

注釈は、それらをサポートするフレームワークを持っている場合にのみ役に立ちます。この例ではBTWはgetAnnotation()がnullを返す;) –

+5

私は人を知らない。この場合(typoがなければ)、フィールド値があいまいです。同じ値を持つ2つのインタフェースを宣言するのと同じように、コンパイラのエラーと同じです。私はこれがフィールドではないことを知っていますが、注釈の値はコンパイル時にすべて解決されますが、そうではありませんか?ここで欠けている機能は、多くの場合非常に役立ちます。ところで、古い投稿を復活させて申し訳ありません:) –

+6

@Slanecは、Springの人がこれらの問題をどのように処理したかを見るためにSpringのソースを見ています。 [AnnotationUtils.findAnnotation(method、annotationType)](http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-core/3.1.1.RELEASE/org/springframework/core/)を参照してください。注釈/ AnnotationUtils.java#AnnotationUtils.findAnnotation%28java.lang.reflect.Method%2Cjava.lang.Class%29) –

29

は注釈型が自動的に継承されることを示します。 継承されたメタ注釈が注釈タイプ 宣言に存在し、ユーザーがクラス 宣言の注釈タイプを照会し、クラス宣言にこの タイプの注釈がない場合、クラスのスーパークラスが自動的に照会されます。 注釈の種類。このプロセスは、このタイプの注釈 が見つかるまで、またはクラス階層(オブジェクト)の先頭に到達するまで繰り返されます( )。スーパークラスにこのタイプのアノテーションがない場合、 クエリは、そのクラスがそのアノテーションを持たないことを示します。 注釈付きの タイプを使用してクラス以外のものに注釈を付ける場合、このメタ注釈タイプは無効です。 このメタ注釈は、注釈が スーパークラスから継承されるだけです。実装されたインタフェースのアノテーションは効果がありません。

一方、JSR 305バリデーターは、ある種の継承ルックアップを行います。あなたはクラスの階層がある場合:

//Person.java 
@Nonnull 
public Integer getAge() {...} 

//Student.java (inherits from Person) 
@Min(5) 
public Integer getAge() {...} 

を次にStudent.getAge()上の効果的な検証が@Nonnull @Min(5)です。 @Nonnullには、@Inheritedのメタ注釈はありません。

+4

これは選択された回答でなければなりません – Ondreju

+2

あなたの例はあなたの答えと矛盾しています。つまり、 '@ Inherited'はclass以外 –

関連する問題