Partie 2 | Comprendre les annotations : principes de base et solutions personnalisées en Java/Kotlin

Dans Partie 1nous avons discuté des principes fondamentaux des annotations en Java et Kotlin, y compris un aperçu de ce que sont les annotations, des différents types d’annotations intégrées comme @Outrepasser, @Obsolète, etc., et comment ils simplifient les tâches de programmation courantes. Nous avons également exploré la structure de base des annotations, comment les définir et l’importance de les utiliser efficacement dans votre code.
Si vous n’avez pas encore consulté la première partie, veuillez le faire d’abord pour acquérir une base solide sur les annotations avant de passer à des concepts plus avancés comme Politiques de rétention, annotations Cibles & Solutions d’annotations personnalisées discuté ici dans la partie 2.
Politiques de conservation des annotations
Après avoir abordé les bases et les types d’annotations, approfondissons maintenant les politiques de rétention, qui jouent un rôle essentiel dans les annotations en Java et Kotlin. Les politiques de conservation déterminent la durée pendant laquelle les métadonnées d’une annotation sont conservées et où elles sont accessibles pendant le cycle de vie de l’application. Ce choix est essentiel car il a un impact sur la façon dont les annotations sont utilisées et traitées et peut garantir qu’elles remplissent leur objectif sans introduire de surcharge inutile dans votre application.
Il existe trois types de politiques de rétention : SOURCE, CLASSEet DURÉE D’EXÉCUTION.
- RetentionPolicy.SOURCE ou AnnotationRetention.SOURCE (Kotlin)
Portée de conservation : Les annotations sont supprimées une fois le code compilé et ne sont pas incluses dans les fichiers .class compilés.
But: Utilisé principalement pour les vérifications au moment de la compilation et la génération de code. Ces annotations sont invisibles au moment de l’exécution.
Exemple de cas d’utilisation : @Outrepasser garantit qu’une méthode remplace une méthode de superclasse, mais elle n’est pas nécessaire au-delà de la compilation.
@Retention(RetentionPolicy.SOURCE) public @interface ExampleSourceAnnotation { }
- RetentionPolicy.CLASS ou dans Kotlin AnnotationRetention.BINARY
Portée de conservation : Les annotations sont incluses dans les fichiers .class mais ne sont pas conservées en mémoire au moment de l’exécution.
But: Utile pour le traitement au niveau du bytecode ou les outils qui manipulent les fichiers .class, tels que les obfuscateurs ou certains outils d’analyse statique.
Rétention par défaut en Java : si aucune politique de rétention n’est spécifiée, les annotations sont par défaut CLASS.
Exemple de cas d’utilisation : Annotations utilisées lors de la compilation qui ne nécessitent pas de traitement d’exécution.
@Retention(RetentionPolicy.CLASS) public @interface ExampleClassAnnotation { }
- RetentionPolicy.RUNTIME AnnotationRetention.RUNTIME (Kotlin)
Portée de conservation: Les annotations sont incluses dans les fichiers .class et sont conservées en mémoire au moment de l’exécution, les rendant accessibles via la réflexion.
But: Ces annotations sont essentielles pour les frameworks et les bibliothèques qui s’appuient sur des métadonnées d’exécution, telles que l’injection de dépendances ou les frameworks ORM.
Exemple de cas d’utilisation: Annotations comme @Entité en veille prolongée ou @OBTENIR dans Retrofit, qui nécessitent un traitement d’exécution.
@Retention(RetentionPolicy.RUNTIME) public @interface ExampleRuntimeAnnotation { }
Pourquoi la politique de rétention est-elle importante ?
Choisir la bonne politique de rétention est crucial pour une utilisation efficace des annotations dans votre projet. Voici un résumé pour vous aider à décider quelle politique de rétention utiliser en fonction de vos besoins :
- SOURCE: utilisez-le lorsque l’annotation est uniquement destinée aux vérifications au moment de la compilation ou à la génération de code. L’annotation n’aura pas d’impact sur le comportement d’exécution.
- CLASSE: choisissez cette option lorsque l’annotation doit être incluse dans le bytecode pour les outils qui manipulent les fichiers .class mais n’est pas requise au moment de l’exécution.
- DURÉE D’EXÉCUTION: Ceci doit être utilisé lorsque l’annotation affecte le comportement d’exécution ou doit être accessible via la réflexion. Il est idéal pour les frameworks qui effectuent l’injection de dépendances, la sérialisation et d’autres tâches d’exécution.
En comprenant et en appliquant la politique de rétention appropriée, vous pouvez vous assurer que vos annotations sont à la fois efficaces et efficientes, en vous assurant qu’elles remplissent leurs rôles prévus sans entraîner de surcharge inutile.
Cibles d’annotation
Maintenant que nous avons expliqué la durée pendant laquelle les annotations restent dans les stratégies de rétention, parlons des endroits où nous pouvons les appliquer. C’est là que les cibles d’annotation entrent en jeu. Les cibles d’annotation définissent les éléments spécifiques de votre code dans lesquels une annotation peut être utilisée. Pensez-y comme si vous mettiez un autocollant : vous pouvez le placer sur un livre, une page ou peut-être simplement sur un mot spécifique. Les cibles d’annotation spécifient exactement où l’annotation est autorisée à aller.
En Java et Kotlin, vous pouvez contrôler le placement des annotations en spécifiant la cible appropriée. Ces objectifs sont définis à l’aide du @Cible méta-annotation.
Voici quelques cibles courantes que vous rencontrerez :

Cible d’annotation
Lorsqu’une annotation est créée sans spécifier de cibles à l’aide de l’option @Cible méta-annotation, elle peut être appliquée à presque tous les éléments du code. Cela inclut les classes, les méthodes, les champs, les constructeurs, les paramètres, etc.
Syntaxe générale
En Java, les cibles sont définies à l’aide du @Cible méta-annotation et constantes de ElementType
import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.METHOD}) public @interface ExampleAnnotation { }
Dans Kotlin, les cibles sont définies à l’aide du @Cible méta-annotation avec des constantes d’Annotation Target.
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class ExampleAnnotation
Si vous appliquez une annotation à un élément qui n’est pas autorisé par la spécification @Target : Le compilateur générera une erreur du type : type d’annotation non applicable à ce type de déclaration
Pourquoi définir des cibles explicitement ?
Clarté: les cibles explicites indiquent clairement aux développeurs l’utilisation prévue d’une annotation, réduisant ainsi le risque d’utilisation abusive.
Maintenabilité: Restreindre l’endroit où une annotation peut être appliquée permet d’éviter toute confusion lorsque le projet se développe ou implique plusieurs contributeurs.
Meilleures pratiques
Définir des cibles explicitement: Toujours préciser @Cible pour éviter une mauvaise utilisation accidentelle.
Utiliser les méta-annotations: Combiner @Cible avec @Rétention pour contrôler le cycle de vie et la portée de votre annotation.
Création d’annotations personnalisées
La création d’annotations personnalisées en Java et Kotlin vous permet de définir les métadonnées qui peuvent être utilisées pour influencer le comportement de votre code. Les annotations personnalisées sont utiles pour mettre en œuvre des préoccupations transversales telles que la journalisation, la validation ou même des comportements personnalisés dans les frameworks. Une annotation personnalisée est une annotation définie par l’utilisateur qui peut être appliquée à des classes, des méthodes, des champs ou d’autres éléments pour fournir des métadonnées pouvant être utilisées par le compilateur ou le runtime. Tout comme les annotations intégrées (@Override, @Deprecated), vous pouvez créer vos propres annotations avec des propriétés, des politiques de rétention et des cibles spécifiques.
Étapes clés pour créer des annotations personnalisées :
- Définissez l’annotation : Utiliser @interface en Java ou classe d’annotation en Kotlin. Spécifiez les métadonnées telles que la politique de rétention et les cibles à l’aide @Rétention et @Cible.
- Ajouter des éléments : Définissez des éléments (similaires aux méthodes) dans l’interface d’annotation pour stocker les valeurs. Fournissez des valeurs par défaut pour les éléments, si nécessaire.
- Traitez l’annotation : Écrivez des processeurs d’annotation pour gérer votre annotation personnalisée, soit au moment de la compilation (à l’aide d’outils comme APT), soit au moment de l’exécution (via la réflexion).
- Appliquer l’annotation : Annotez des classes, des méthodes ou des champs avec votre annotation personnalisée.
Exemple 1 : Annotation personnalisée pour la liaison de vue @BindView
Prenons un exemple où nous créons une annotation personnalisée similaire à Couteau à beurre @BindViewce qui simplifie la liaison de vue.
But:
- Simplifie la liaison de vue : Cette annotation réduira le besoin d’écrire un passe-partout findViewById appels.
- Scénario d’utilisation : Réduire le code passe-partout : au lieu d’appeler manuellement findViewById() à chaque fois, utilisez @BindView pour annoter vos champs. La méthode utilitaire gérera automatiquement la liaison.
- Politique de conservation : @Rétention(RetentionPolicy.RUNTIME) Conserve l’annotation au moment de l’exécution afin qu’elle soit accessible via la réflexion.
- Cible: @Target (ElementType.FIELD) sera appliqué aux champs où les vues sont liées
Étape 1 : Définir le @BindView Annotations en Java

Définir l’annotation @BindView
Étape 2 : implémentez la méthode Bind en la traitant
Voici une méthode qui traite le @BindView annotation et lie les vues

Implémenter la méthode Bind
Étape 3 : Dans votre activité, vous pouvez désormais utiliser l’annotation @BindView personnalisée pour lier des vues :

Appliquer l’annotation
Avantages de l’utilisation d’annotations personnalisées
- Réduit le code passe-partout : En écrivant findViewById() car chaque vue peut encombrer votre code. Des annotations comme @BindView réduire considérablement le nombre de lignes.
- Code du nettoyeur : L’utilisation d’annotations maintient le code propre en rendant implicite la logique de liaison de l’interface utilisateur. Cela améliore la lisibilité et la maintenabilité.
- Utilitaire réutilisable : Une fois que vous avez écrit une méthode utilitaire (comme bind()), elle peut être réutilisée sur plusieurs activités ou fragments sans effort supplémentaire.
Prenons un autre exemple pour démontrer l’intégration d’annotations personnalisées dans des frameworks.
Exemple 2 : Création d’un cadre d’injection de dépendances simple
But: Nous allons créer une annotation personnalisée de base, @Injecter pour démontrer comment des frameworks comme Dagger gèrent l’injection de dépendances.
1. Définir le @Injecter Annotation

Définition de l’annotation @Inject
2. Mise en place d’un service simple Définissons un service que nous souhaitons injecter dans une classe client

Mise en place d’un service simple
3. Utilisation @Injecter dans une activité Voici comment utiliser l’annotation @Inject pour marquer un champ dans une activité

Utiliser @Inject dans une activité
4. Écriture du processeur d’injection de dépendances La classe Injector analyse les champs de l’objet donné (dans ce cas, MainActivity) et injecte des dépendances pour les champs annotés avec @Injecter

Écriture du processeur d’injection de dépendances
Avantages de l’utilisation @Injecter Annotations personnalisées dans Android
- Élimine le code passe-partout : Le @Injecter L’annotation supprime le besoin d’initialisation manuelle des champs.
- Améliore la lisibilité : Les champs annotés indiquent clairement leur objectif et réduisent l’encombrement dans le onCréer() ou code d’initialisation.
- Échelle bien : À mesure que l’application se développe, l’injection de dépendances garantit une meilleure modularité et testabilité.
- Compatibilité du framework : Cette approche peut être étendue et affinée pour implémenter des modèles DI avancés, tels que ceux utilisés dans Dagger ou Hilt.
Continuez à apprendre ! Continuez à coder !
Les annotations personnalisées offrent une grande flexibilité dans votre processus de développement. Suivez-nous pendant que nous approfondissons le traitement des annotations et les cas d’utilisation plus avancés à l’avenir !
VOUS TROUVEZ CECI UTILE ? PARTAGEZ-LE
Source link