我有一个带注释方法的界面。注释标有@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():[]
所以问题是obj.m()
为什么@TestAnnotation
不会@TestAnnotation
实现@Inherited
标记为{{1}}的方法?
答案 0 :(得分:18)
来自@Inherited javadoc:
请注意,如果使用带注释的类型来注释除类之外的任何内容,则此元注释类型无效。另请注意,此元注释仅导致注释从超类继承;已实现的接口上的注释无效。
总之,它不适用于方法。
答案 1 :(得分: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());
}