アノテーションInherited

某ソースを眺めてたら、アノテーションで@Inheritedというのが使われていたけど、
Javadocを読んでも何を言ってんだかよくわからない。
すこし調べてみると、継承したクラスにそのアノテーションが引き継がれるかどうか、
という意味があるらしい。
というわけで、実際に使って確かめてみた。


まずは、アノテーション
Hogeは@Inheritedアリで、Fooはナシ。


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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Foo {
String value();
}


次にテストコード。
Parentクラスに@Hogeと@Fooのアノテーションを付ける。
Parentクラスを継承したChildクラスには、アノテーションを付けない。
mainメソッドでは、Parent・Childにあるアノテーションを表示している。


public class Test {

@Hoge("hello hoge")
@Foo("hello foo")
public static class Parent {
}

public static class Child extends Parent {
}

public static void main(String[] args) {
System.out.println("Parent:");
printAnnotation(Parent.class);

System.out.println();
System.out.println("Child:");
printAnnotation(Child.class);
}

private static void printAnnotation(Class clazz) {
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation.toString());
}
}

}


これの実行結果


Parent:
@jp.gr.java_conf.ykhr.test.Foo(value=hello foo)
@jp.gr.java_conf.ykhr.test.Hoge(value=hello hoge)

Child:
@jp.gr.java_conf.ykhr.test.Hoge(value=hello hoge)

@InheritedがあるアノテーションHogeは、Childクラスに継承される。
逆に@InheritedのないアノテーションFooは、Childクラスには継承されない。
・・・ということらしい。


注意点としては、@Inheritedはクラスのアノテーションのみ有効らしく、Javadoc曰く
「注釈付きの型を使用してクラス以外のものに注釈が設定されている場合、このメタ注釈型は無効です。」
ということらしい。
ついでに、「このメタ注釈の機能はスーパークラスから注釈を継承させるだけであり、
実装されたインタフェースに対する注釈は無効であることにも留意してください。」
とのことです。


あと30分早く言ってくれれば、試さなかったものを・・・。