问题
I have a parent class Parent and a child class Child, defined thus:
class Parent {
@MyAnnotation(\"hello\")
void foo() {
// implementation irrelevant
}
}
class Child {
@Override
foo() {
// implementation irrelevant
}
}
If I obtain a Method reference to Child::foo, will childFoo.getAnnotation(MyAnnotation.class) give me @MyAnnotation? Or will it be null?
I\'m interested more generally in how or whether annotation works with Java inheritance.
回答1:
Copied verbatim from http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations.html#annotation-inheritance:
Annotation Inheritance
It is important to understand the rules relating to inheritance of annotations, as these have a bearing on join point matching based on the presence or absence of annotations.
By default annotations are not inherited. Given the following program
@MyAnnotation
class Super {
@Oneway public void foo() {}
}
class Sub extends Super {
public void foo() {}
}
Then
Subdoes not have theMyAnnotationannotation, andSub.foo()is not an@Onewaymethod, despite the fact that it overridesSuper.foo()which is.If an annotation type has the meta-annotation
@Inheritedthen an annotation of that type on a class will cause the annotation to be inherited by sub-classes. So, in the example above, if theMyAnnotationtype had the@Inheritedattribute, thenSubwould have theMyAnnotationannotation.
@Inheritedannotations are not inherited when used to annotate anything other than a type. A type that implements one or more interfaces never inherits any annotations from the interfaces it implements.
回答2:
You found your answer already: there is no provision for method-annotation inheritance in the JDK.
But climbing the super-class chain in search of annotated methods is also easy to implement:
/**
* Climbs the super-class chain to find the first method with the given signature which is
* annotated with the given annotation.
*
* @return A method of the requested signature, applicable to all instances of the given
* class, and annotated with the required annotation
* @throws NoSuchMethodException If no method was found that matches this description
*/
public Method getAnnotatedMethod(Class<? extends Annotation> annotation,
Class c, String methodName, Class... parameterTypes)
throws NoSuchMethodException {
Method method = c.getMethod(methodName, parameterTypes);
if (method.isAnnotationPresent(annotation)) {
return method;
}
return getAnnotatedMethod(annotation, c.getSuperclass(), methodName, parameterTypes);
}
回答3:
Using Spring Core you can resolve with
AnnotationUtils.java
回答4:
While the answer to the question as asked is that Java's Method.getAnnotation() does not consider overridden methods, sometimes it is useful to find these annotations. Here is a more complete version of Saintali's answer that I'm currently using:
public static <A extends Annotation> A getInheritedAnnotation(
Class<A> annotationClass, AnnotatedElement element)
{
A annotation = element.getAnnotation(annotationClass);
if (annotation == null && element instanceof Method)
annotation = getOverriddenAnnotation(annotationClass, (Method) element);
return annotation;
}
private static <A extends Annotation> A getOverriddenAnnotation(
Class<A> annotationClass, Method method)
{
final Class<?> methodClass = method.getDeclaringClass();
final String name = method.getName();
final Class<?>[] params = method.getParameterTypes();
// prioritize all superclasses over all interfaces
final Class<?> superclass = methodClass.getSuperclass();
if (superclass != null)
{
final A annotation =
getOverriddenAnnotationFrom(annotationClass, superclass, name, params);
if (annotation != null)
return annotation;
}
// depth-first search over interface hierarchy
for (final Class<?> intf : methodClass.getInterfaces())
{
final A annotation =
getOverriddenAnnotationFrom(annotationClass, intf, name, params);
if (annotation != null)
return annotation;
}
return null;
}
private static <A extends Annotation> A getOverriddenAnnotationFrom(
Class<A> annotationClass, Class<?> searchClass, String name, Class<?>[] params)
{
try
{
final Method method = searchClass.getMethod(name, params);
final A annotation = method.getAnnotation(annotationClass);
if (annotation != null)
return annotation;
return getOverriddenAnnotation(annotationClass, method);
}
catch (final NoSuchMethodException e)
{
return null;
}
}
来源:https://stackoverflow.com/questions/10082619/how-do-java-method-annotations-work-in-conjunction-with-method-overriding