GuiceのAOPを使用して、いくつかのメソッド呼び出しをインターセプトしました。私のクラスはインターフェイスを実装しています。Guiceが適切なメソッドを選択できるように、インターフェイスメソッドに注釈を付けたいと思います。アノテーションのタイプに Inherited アノテーションが付けられている場合でも、クラスを実装するアノテーションはInheritedのJava doc:
また、このメタ注釈は、注釈がスーパークラスからのみ継承されることに注意してください。実装されたインターフェースの注釈は効果がありません。
この理由は何でしょうか?オブジェクトのクラスが実行時に実装するすべてのインターフェイスを知ることはそれほど難しいことではないので、この決定の背後には正当な理由がなければなりません。
その理由は、そうしないと多重継承の問題が発生するからだと思います。
例:
@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 から:
注釈タイプが自動的に継承されることを示します。継承されたメタ注釈が注釈型宣言に存在し、ユーザーがクラス宣言で注釈型を照会し、クラス宣言にこの型の注釈がない場合、クラスのスーパークラスは注釈型に対して自動的にクエリされます。このプロセスは、このタイプの注釈が見つかるか、クラス階層の最上位(オブジェクト)に達するまで繰り返されます。このタイプの注釈を持つスーパークラスがない場合、クエリは、問題のクラスにそのような注釈がないことを示します。注釈付きのタイプを使用してクラス以外の注釈を付ける場合、このメタ注釈タイプは効果がないことに注意してください。また、このメタ注釈は、注釈がスーパークラスからのみ継承されることに注意してください。実装されたインターフェースの注釈は効果がありません。
一方、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
_メタ注釈がありません。