2016-08-16 1 views
2

Les annotations de type Java 8 (JSR 308) permettent aux vérificateurs de type d'effectuer une analyse de code statique. Par exemple, The Checker Framework peut vérifier la nullité possible via @NonNull annotations.@Rétention d'annotations de vérificateur de type Java

Divers projets définissent leurs propres annotations non nulle, par exemple:

  • org.checkerframework.checker.nullness.qual.NonNull
  • edu.umd.cs.findbugs.annotations.NonNull
  • javax.annotation.Nonnull
  • javax.validation.constraints.NotNull
  • lombok.NonNull
  • org.eclipse.jdt.annotation.NonNull
  • etc. (voir The Checker Framework Manual, section 3.7)

Pour ces annotations, je me attends @interface d'avoir @Retention(RetentionPolicy.CLASS), car ils ne sont généralement pas nécessaires à l'exécution. Plus important encore, le code n'a aucune dépendance d'exécution sur la bibliothèque respective.

Alors que org.eclipse.jdt.annotation.NonNull suit cette approche, la plupart des autres annotations non nulle, comme javax.annotation.Nonnull (JSR 305) et org.checkerframework.checker.nullness.qual.NonNull lui-même, ont @Retention(RetentionPolicy.RUNTIME). Y a-t-il une raison particulière pour le RetentionPolicy.RUNTIME dans ces annotations? Clarification: Le Framework Checker prend en charge les annotations dans les commentaires pour des raisons de compatibilité ascendante. Cependant, l'utilisation de Java 8 pour éviter les dépendances à l'exécution semble être un hack sale.

Répondre

3

Ceci est une bonne question. Aux fins de la vérification statique au moment de la compilation, CLASS la rétention serait suffisante. Notez que la rétention SOURCE ne serait pas suffisante, en raison de la compilation séparée: lors de la vérification de type d'une classe, le compilateur doit lire les annotations sur les bibliothèques qu'il utilise et les bibliothèques compilées séparément sont disponibles au compilateur uniquement en tant que fichiers de classe.

Les concepteurs d'annotation ont utilisé la rétention RUNTIME pour autoriser les outils à effectuer des opérations d'exécution. Cela peut inclure la vérification des annotations (comme une déclaration assert), la vérification de type du code chargé dynamiquement, la vérification des lancers et des opérations instanceof, la résolution plus précise de la réflexion, etc. Pas beaucoup de tels outils existent aujourd'hui, mais les concepteurs d'annotation voulaient les accueillir dans le futur.

Vous avez remarqué qu'avec @Retention(RetentionPolicy.CLASS), "le code n'a aucune dépendance d'exécution sur la bibliothèque respective". C'est vrai aussi avec @Retention(RetentionPolicy.RUNTIME)! Voir cette question de débordement de pile: Why doesn't a missing annotation cause a ClassNotFoundException at runtime?. En résumé, l'utilisation de la rétention CLASS entraîne une quantité d'espace négligeable au moment de l'exécution, permet plus d'utilisations potentielles dans le futur et n'introduit pas de dépendance au moment de l'exécution.

Dans le cas du cadre Checker, il offre des tests d'exécution tels que isRegex(String). Si votre code utilise de telles méthodes, votre code dépendra de la bibliothèque d'exécution de Checker Framework (qui est plus petite que l'intégralité de Checker Framework elle-même).

+0

Remarque associée pour les classes annotées moqueuses avec mockito (version 2.2.0): While RetentionPolicy. RUNTIME signifie qu'une annotation présente dans le binaire ne doit pas être disponible à l'exécution, https://bugs.openjdk.java.net/browse/JDK-8152174 provoque une exception NullPointerException dans Java 8 en se moquant d'une classe annotée pour laquelle le l'annotation n'est pas disponible sur le chemin de classe. –

1

Chaque annotation a son but!

javax.validation.constraints.NotNull 

Ce celles est défini par la spécification de validation de haricot et est utilisé pour effectuer une vérification non nulle lors de l'exécution, il doit être conservé à l'exécution pour effectuer, par exemple, une forme valdiation ...

@ RetentionPolicy.SOURCE => habituellement utilisé pour la documentation @ RetentionPocily.CLASS => permet de donner des informations au compilateur mais pas à la JVM (par exemple, pour générer du code lors de la compilation) @ RetentionPolicy.RUNTIME => allow récupérer les informations d'annotation au niveau de la JVM (donc lors de l'exécution).

Cordialement,

Loïc

+0

Oui 'javax.validation.constraints.NotNull' a un but d'exécution. Mais 'javax.annotation.Nonnull' et' org.checkerframework.checker.nullness.qual.NonNull' n'ont aucun but d'exécution IMO. –

+1

Il n'y a pas de réponse globale à votre question, c'est au créateur de l'annotation de définir si elle doit être conservée en cours d'exécution ou non. Voir ce fil de travail SOW pour un indice: http://stackoverflow.com/questions/14810030/javax-annotation-nonnull-vs-assert – loicmathieu