14

注釈付きメソッドとのインターフェースがあります。注釈は でマークされて@Inheritedいるので、実装者がそれを継承することを期待しています。ただし、そうではありません。

コード:

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Example {

    public static void main(String[] args) throws SecurityException, NoSuchMethodException {
        TestInterface obj = new TestInterface() {
            @Override
            public void m() {}
        };

        printMethodAnnotations(TestInterface.class.getMethod("m"));
        printMethodAnnotations(obj.getClass().getMethod("m"));
    }

    private static void printMethodAnnotations(Method m) {
        System.out.println(m + ": " + Arrays.toString(m.getAnnotations()));
    }
}

interface TestInterface {
    @TestAnnotation
    public void m();
}

@Retention(RetentionPolicy.RUNTIME)
@Inherited
@interface TestAnnotation {}

上記のコードは次を出力します。

public abstract void annotations.TestInterface.m(): [@annotations.TestAnnotation()]

public void annotations.Example$1.m(): []

問題は、 which is でマークされたメソッドを実装しているにもかかわらず、 obj.m()have が実装されていないのはなぜですか?@TestAnnotation@TestAnnotation@Inherited

4

3 に答える 3

31

javadocからjava.lang.annotation.Inherited

注釈付きの型がクラス以外のものに注釈を付けるために使用されている場合、このメタ注釈型は効果がないことに注意してください。また、このメタアノテーションはアノテーションをスーパークラスから継承するだけであることにも注意してください。実装されたインターフェースの注釈は効果がありません。

于 2012-09-14T17:00:28.783 に答える
22

@Inherited javadocから:

注釈付きの型がクラス以外のものに注釈を付けるために使用されている場合、このメタ注釈型は効果がないことに注意してください。このメタアノテーションは、スーパークラスから継承されるアノテーションのみを引き起こすことにも注意してください。実装されたインターフェースの注釈は効果がありません。

要約すると、メソッドには適用されません。

于 2012-09-14T17:00:41.270 に答える
3

または、リフレクションを使用して同じ情報を取得することもできます。メソッドは次のprintMethodAnnotationsように書き直すことができます。

private static void printMethodAnnotations(Method m) {
    Class<?> methodDeclaredKlass = m.getDeclaringClass();
    List<Class<?>> interfases = org.apache.commons.lang3.ClassUtils.getAllInterfaces(methodDeclaredKlass);
    List<Annotation> annotations = new ArrayList<>();
    annotations.addAll(Arrays.asList(m.getAnnotations()));
    for (Class<?> interfase : interfases) {
        for (Method interfaseMethod : interfase.getMethods()) {
            if (areMethodsEqual(interfaseMethod, m)) {
                annotations.addAll(Arrays.asList(interfaseMethod.getAnnotations()));
                continue;
            }
        }
    }
    System.out.println(m + "*: " + annotations);
}

private static boolean areMethodsEqual(Method m1, Method m2) {
    // return type, Modifiers are not required to check, if they are not appropriate match then it will be a compile
    // time error. This needs enhancements for Generic types parameter ?
    return m1.getName().equals(m2.getName()) && Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes());
}
于 2017-01-31T15:22:28.870 に答える