¿Cómo fuerzo a una subclase de Java a definir una anotación?
-
01-07-2019 - |
Pregunta
Si una clase definió una anotación, ¿es posible de alguna manera forzar a su subclase a definir la misma anotación?
Por ejemplo, tenemos un par de clase/subclase simple que comparte el @Author @interface.
Lo que me gustaría hacer es obligar a cada subclase adicional a definir lo mismo @Author
anotación, impidiendo una RuntimeException
en algún lugar del camino.
PruebaClass.java:
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@interface Author { String name(); }
@Author( name = "foo" )
public abstract class TestClass
{
public static String getInfo( Class<? extends TestClass> c )
{
return c.getAnnotation( Author.class ).name();
}
public static void main( String[] args )
{
System.out.println( "The test class was written by "
+ getInfo( TestClass.class ) );
System.out.println( "The test subclass was written by "
+ getInfo( TestSubClass.class ) );
}
}
PruebaSubClass.java:
@Author( name = "bar" )
public abstract class TestSubClass extends TestClass {}
Sé que puedo enumerar todas las anotaciones en tiempo de ejecución y comprobar si faltan @Author
, pero realmente me gustaría hacer esto en tiempo de compilación, si es posible.
Solución
Puedes hacerlo con JSR 269, en tiempo de compilación.Ver : http://today.java.net/pub/a/today/2006/06/29/validate-java-ee-annotations-with-annotation-processors.html#pluggable-annotation-processing-api
Otros consejos
Estoy bastante seguro de que esto es imposible de hacer en tiempo de compilación.
Sin embargo, esta es una tarea obvia para una prueba "unitaria".Si tiene convenciones como ésta que le gustaría aplicar, pero que pueden ser difíciles o imposibles de verificar con el compilador, las pruebas "unitarias" son una forma sencilla de verificarlas.
Otra posibilidad es implementar una regla personalizada en un analizador estático.Aquí también hay muchas opciones.
(Pongo la unidad entre comillas, ya que en realidad se trata de una prueba de convenciones, más que de una unidad específica.Pero debería ejecutarse junto con sus pruebas unitarias).
Podrías hacer una anotación (p. ej.@EnforceAuthor) con @Inherited en la superclase y usa anotaciones del compilador (desde Java 1.6) para ponerse al día en tiempo de compilación.Luego tiene una referencia a la subclase y puede verificar si otra anotación (p. ej.@Autor)) falta.Esto permitiría cancelar la compilación con un mensaje de error.