Quelqu'un peut-il expliquer clairement les différences pratiques entre les Java.lang.annotation.RetentionPolicy
constantes SOURCE
, CLASS
et RUNTIME
?
De plus, je ne sais pas exactement ce que signifie "conserver l'annotation".
RetentionPolicy.SOURCE
: Jeter lors de la compilation. Ces annotations n'ont aucun sens une fois la compilation terminée, elles ne sont donc pas écrites dans le bytecode.
Exemple:@Override
,@SuppressWarnings
RetentionPolicy.CLASS
: Jeter pendant le chargement de la classe. Utile lorsque vous effectuez un post-traitement au niveau du bytecode. Assez étonnamment, c'est le défaut.
RetentionPolicy.RUNTIME
: Ne pas jeter. L'annotation doit être disponible pour la réflexion lors de l'exécution. Exemple:@Deprecated
Source: L'ancienne URL est morte maintenant hunter_meta et remplacé par hunter-meta-2-098036 . Au cas où même cela tomberait, je télécharge l'image de la page.
Image (Cliquez avec le bouton droit de la souris et sélectionnez 'Ouvrir l'image dans un nouvel onglet/une nouvelle fenêtre')
Selon vos commentaires sur la décompilation des classes, voici comment cela devrait fonctionner:
RetentionPolicy.SOURCE
: N'apparaîtra pas dans la classe décompilée
RetentionPolicy.CLASS
: Apparaît dans la classe décompilée, mais ne peut pas être inspecté au moment de l'exécution avec une réflexion avec getAnnotations()
RetentionPolicy.RUNTIME
: Apparaît dans la classe décompilée et peut être inspecté à l'exécution avec une réflexion avec getAnnotations()
Exemple minimal exécutable
Niveau de langue :
import Java.lang.annotation.Retention;
import Java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.SOURCE)
@interface RetentionSource {}
@Retention(RetentionPolicy.CLASS)
@interface RetentionClass {}
@Retention(RetentionPolicy.RUNTIME)
@interface RetentionRuntime {}
public static void main(String[] args) {
@RetentionSource
class B {}
assert B.class.getAnnotations().length == 0;
@RetentionClass
class C {}
assert C.class.getAnnotations().length == 0;
@RetentionRuntime
class D {}
assert D.class.getAnnotations().length == 1;
}
Niveau de Bytecode : en utilisant javap
, nous observons que la classe annotée Retention.CLASS
Obtient un RuntimeInvisible attribut de classe:
#14 = Utf8 LRetentionClass;
[...]
RuntimeInvisibleAnnotations:
0: #14()
tandis que l'annotation Retention.RUNTIME
obtient un attribut de classe RuntimeVisible :
#14 = Utf8 LRetentionRuntime;
[...]
RuntimeVisibleAnnotations:
0: #14()
et le Runtime.SOURCE
annoté .class
ne reçoit aucune annotation.
Exemples sur GitHub pour vous permettre de jouer.
RetentionPolicy.SOURCE
: L'annotation serait disponible dans le code source du programme, ni dans le fichier .class, ni au moment de l'exécution. Utilisé par le compilateur.RetentionPolicy.CLASS
: L'annotation serait dans le fichier .class mais ne serait pas disponible au moment de l'exécution. Utilisé par des outils de manipulation de code octet tels que ASM, effectuer les modificationsRetentionPolicy.RUNTIME
: L'annotation serait disponible au fichier .class et à l'exécution, pour inspection via Java réflexion via getAnnotations()
.
Stratégie de rétention: une stratégie de rétention détermine à quel moment une annotation est supprimée.
1.SOURCE: annotation retained only in the source file and is discarded
during compilation.
2.CLASS: annotation stored in the .class file during compilation,
not available in the run time.
3.RUNTIME: annotation stored in the .class file and available in the run time.
Une stratégie de rétention est spécifiée à l'aide des annotations intégrées de Java: @Retention.