親クラスに定義されたアノテーションはサブクラスで継承されるか?インターフェース上のアノテーションは?

テスト環境と設定

以下の条件でアノテーションの継承挙動を検証します。

  • 親クラスのクラスレベルとメソッドレベルにカスタムアノテーションを定義
  • サブクラスが以下の3つのケースをテスト
    • 抽象メソッドの実装
    • メソッドの継承
    • メソッドの上書き

public class AnnotationInheritanceTest {

    @Retention(RetentionPolicy.RUNTIME)
    public @interface CustomAnnotation {
        String value();
    }

    @CustomAnnotation("スーパークラスのアノテーション")
    public abstract class BaseClass {
        @CustomAnnotation("抽象メソッドのアノテーション")
        public abstract void abstractMethod();

        @CustomAnnotation("継承メソッドのアノテーション")
        public void inheritedMethod() {
            System.out.println("BaseClass implementation");
        }

        @CustomAnnotation("上書きメソッドのアノテーション")
        public void overridableMethod() {
            System.out.println("BaseClass implementation");
        }
    }

    public class DerivedClass extends BaseClass {
        // 抽象メソッドの実装
        @Override
        public void abstractMethod() {
            System.out.println("DerivedClass implementation");
        }

        // メソッドの上書き
        @Override
        public void overridableMethod() {
            System.out.println("DerivedClass implementation");
        }
    }

    public static void main(String[] args) throws Exception {
        Class<DerivedClass> clazz = DerivedClass.class;

        // クラスレベルのアノテーションテスト
        if (clazz.isAnnotationPresent(CustomAnnotation.class)) {
            System.out.println("クラスレベルアノテーション取得成功: " + 
                clazz.getAnnotation(CustomAnnotation.class).value());
        } else {
            System.out.println("クラスレベルアノテーション取得失敗");
        }

        // 抽象メソッドテスト
        Method abstractMethod = clazz.getMethod("abstractMethod");
        if (abstractMethod.isAnnotationPresent(CustomAnnotation.class)) {
            System.out.println("抽象メソッドアノテーション取得成功: " + 
                abstractMethod.getAnnotation(CustomAnnotation.class).value());
        } else {
            System.out.println("抽象メソッドアノテーション取得失敗");
        }

        // 継承メソッドテスト
        Method inheritedMethod = clazz.getMethod("inheritedMethod");
        if (inheritedMethod.isAnnotationPresent(CustomAnnotation.class)) {
            System.out.println("継承メソッドアノテーション取得成功: " + 
                inheritedMethod.getAnnotation(CustomAnnotation.class).value());
        } else {
            System.out.println("継承メソッドアノテーション取得失敗");
        }

        // 上書きメソッドテスト
        Method overridenMethod = clazz.getMethod("overridableMethod");
        if (overridenMethod.isAnnotationPresent(CustomAnnotation.class)) {
            System.out.println("上書きメソッドアノテーション取得成功: " + 
                overridenMethod.getAnnotation(CustomAnnotation.class).value());
        } else {
            System.out.println("上書きメソッドアノテーション取得失敗");
        }
    }
}

テスト結果(@Inherited未使用時)


クラスレベルアノテーション取得失敗
抽象メソッドアノテーション取得失敗
継承メソッドアノテーション取得成功: 継承メソッドのアノテーション
上書きメソッドアノテーション取得失敗

テスト結果(@Inherited使用時)


クラスレベルアノテーション取得成功: スーパークラスのアノテーション
抽象メソッドアノテーション取得失敗
継承メソッドアノテーション取得成功: 継承メソッドのアノテーション
上書きメソッドアノテーション取得失敗

インターフェースの場合


public class InterfaceAnnotationTest {

    @Retention(RetentionPolicy.RUNTIME)
    public @interface CustomAnnotation {
        String value();
    }

    @CustomAnnotation("インターフェースのアノテーション")
    public interface BaseInterface {
        @CustomAnnotation("インターフェースメソッドのアノテーション")
        void interfaceMethod();
    }

    public class ImplementationClass implements BaseInterface {
        @Override
        public void interfaceMethod() {
            System.out.println("ImplementationClass implementation");
        }
    }

    public static void main(String[] args) throws Exception {
        Class<ImplementationClass> clazz = ImplementationClass.class;

        // インターフェースレベルアノテーションテスト
        for (Class<?> iface : clazz.getInterfaces()) {
            if (iface.isAnnotationPresent(CustomAnnotation.class)) {
                System.out.println("インターフェースアノテーション取得成功: " + 
                    iface.getAnnotation(CustomAnnotation.class).value());
            }
        }

        // メソッドレベルアノテーションテスト
        for (Method method : clazz.getMethods()) {
            if (method.isAnnotationPresent(CustomAnnotation.class)) {
                System.out.println("メソッドアノテーション取得成功: " + 
                    method.getAnnotation(CustomAnnotation.class).value());
            }
        }
    }
}

インターフェーステスト結果


インターフェースアノテーション取得成功: インターフェースのアノテーション
メソッドアノテーション取得成功: インターフェースメソッドのアノテーション

タグ: JavaAnnotations InheritanceMechanics InterfaceAnnotations ReflectionAPI

8月1日 00:54 投稿