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 {}

上面的代码打印:

公共抽象 void annotations.TestInterface.m(): [@annotations.TestAnnotation()]

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

obj.m()所以问题是@TestAnnotation尽管它实现了一个标记为@TestAnnotationis的方法,但为什么没有@Inherited呢?

4

3 回答 3

31

来自的javadocsjava.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 回答