Comment forcer une sous-classe Java à définir une annotation?
-
01-07-2019 - |
Question
Si une classe définit une annotation, est-il possible de forcer sa sous-classe à définir la même annotation?
Par exemple, nous avons une simple paire classe / sous-classe qui partage le @Author @interface.
.
Ce que je voudrais faire, c'est forcer chaque sous-classe supplémentaire à définir la même annotation @Author
, en empêchant une RuntimeException
quelque part dans l'avenir.
TestClass.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 ) );
}
}
TestSubClass.java:
@Author( name = "bar" )
public abstract class TestSubClass extends TestClass {}
Je sais que je peux énumérer toutes les annotations au moment de l'exécution et rechercher le @Author
manquant, mais j'aimerais vraiment le faire au moment de la compilation, si possible.
La solution
Vous pouvez le faire avec JSR 269, au moment de la compilation. Voir: http://today.java.net/pub/a/today/2006/06/29/validate-java-ee-annotations-with-annotation-processors.html#pluggable- annotation-processing-api
Autres conseils
Je suis tout à fait sûr que cela est impossible à réaliser au moment de la compilation.
Cependant, cette tâche est évidente pour un test "d'unité". Si vous avez des conventions de ce type que vous souhaiteriez appliquer, mais qu'il peut être difficile voire impossible de vérifier avec le compilateur, les tests "d'unité" constituent un moyen simple de les vérifier.
Une autre possibilité consiste à implémenter une règle personnalisée dans un analyseur statique. Il y a beaucoup d'options ici aussi.
(J'ai mis l'unité entre guillemets, étant donné qu'il s'agit en réalité d'un test de conventions plutôt que d'une unité spécifique. Mais il devrait être exécuté en même temps que vos tests d'unités.)
Vous pouvez créer une annotation (par exemple, @EnforceAuthor) avec @Inherited dans la superclasse et utiliser des annotations du compilateur (depuis Java 1.6) pour rattraper son retard au moment de la compilation. Ensuite, vous avez une référence à la sous-classe et pouvez vérifier si une autre annotation (par exemple, @Author)) est manquante. Cela permettrait d'annuler la compilation avec un message d'erreur.