2011-01-20 18 views
91

He estado usando el AOP de Guice para interceptar algunas llamadas a métodos. Mi clase implementa una interfaz y me gustaría anotar los métodos de interfaz para que Guice pueda seleccionar los métodos correctos. Incluso si el tipo de anotación se anota con Inherited anotación de la implementación de la clase no hereda la anotación como se indica en el documento de java Hereditaria:¿Por qué las clases de Java no heredan las anotaciones de las interfaces implementadas?

Tenga en cuenta también que este meta-anotación sólo causa anotaciones para ser heredados de superclases; Las anotaciones en las interfaces implementadas no tienen ningún efecto.

¿Cuál podría ser el motivo de esto? Conocer todas las interfaces que la clase de un objeto implementa en tiempo de ejecución no es tan difícil, por lo que debe haber una buena razón detrás de esta decisión.

Respuesta

109

Yo diría que la razón es que, de lo contrario, se produciría un problema de herencia múltiple.

Ejemplo:

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) @Inherited 
public @interface Baz { String value(); } 

public interface Foo{ 
    @Baz("baz") void doStuff(); 
} 

public interface Bar{ 
    @Baz("phleem") void doStuff(); 
} 

public class Flipp{ 
    @Baz("flopp") public void doStuff(){} 
} 

public class MyClass extends Flipp implements Foo, Bar{} 

Si hago esto:

MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value() 

cuál es el resultado va a ser? 'baz', 'phleem' o 'flopp'?


Por esta razón, las anotaciones en las interfaces rara vez son útiles.

+8

Las anotaciones en las interfaces solo son útiles si tiene un marco que las admite.Por cierto, en este ejemplo getAnnotation() devuelve nulo;) –

+5

No sé, gente. En este caso (si el error no estaba allí), esperaría un 'El valor del campo es ambiguo. -como el error del compilador al igual que con dos interfaces que declaran la misma constante con diferentes valores. Sé que esto no es un campo, pero los valores de las anotaciones se resuelven en tiempo de compilación, ¿no? La función que nos falta aquí sería muy útil en muchos casos. Perdón por revivir una publicación anterior, por cierto :). –

+6

@Slanec eche un vistazo a la forma en que las fuentes de Spring ven cómo los chicos de Spring solucionaron estos problemas. Ver [AnnotationUtils.findAnnotation (method, annotationType)] (http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-core/3.1.1.RELEASE/org/springframework/core/ annotation/AnnotationUtils.java # AnnotationUtils.findAnnotation% 28java.lang.reflect.Method% 2Cjava.lang.Class% 29) –

29

Desde el Javadoc para @Inherited:

indica que un tipo de anotación se hereda de forma automática. Si una metaanotación heredada está presente en una declaración de tipo anotación , y el usuario consulta el tipo de anotación en una declaración de clase , y la declaración de clase no tiene anotación para este tipo , se consultará automáticamente la superclase de la clase el tipo de anotación. Este proceso se repetirá hasta que se encuentre una anotación para este tipo, o se llegue a la parte superior de la jerarquía de clases (Objeto) . Si ninguna superclase tiene una anotación para este tipo, la consulta indicará que la clase en cuestión no tiene dicha anotación. Tenga en cuenta que este tipo de metarotación no tiene efecto si el tipo anotado se utiliza para anotar cualquier cosa que no sea una clase. Tenga en cuenta también que esta metaanotación solo hace que las anotaciones se hereden de las superclases ; las anotaciones en las interfaces implementadas no tienen ningún efecto.

Por otro lado, los validadores JSR 305 hacen algún tipo de búsqueda de herencia. Si usted tiene una jerarquía de clases:

//Person.java 
@Nonnull 
public Integer getAge() {...} 

//Student.java (inherits from Person) 
@Min(5) 
public Integer getAge() {...} 

A continuación, las validaciones eficaces sobre Student.getAge() son @Nonnull @Min(5). @Nonnull no tiene @Inherited meta-anotación.

+4

Esta debería ser la respuesta seleccionada – Ondreju

+2

Su ejemplo contradice su respuesta, que dice que '@ Inherited' no tiene ningún efecto sobre otra cosa que no sea la clase –

Cuestiones relacionadas