Types d'annotations Java
Types d'annotations Java
Dans ce didacticiel, nous allons découvrir différents types d'annotations Java à l'aide d'exemples.
Les annotations Java sont des métadonnées (données sur les données) pour le code source de notre programme. Il existe plusieurs annotations prédéfinies fournies par Java SE. De plus, nous pouvons également créer des annotations personnalisées selon nos besoins.
Si vous ne savez pas ce que sont les annotations, consultez le didacticiel sur les annotations Java.
Ces annotations peuvent être classées comme :
1. Annotations prédéfinies
@Deprecated
@Override
@SuppressWarnings
@SafeVarargs
@FunctionalInterface
2. Annotations personnalisées
3. Méta-annotations
@Retention
@Documented
@Target
@Inherited
@Repeatable
Types d'annotations prédéfinis
1. @Obsolète
Le @Deprecated
annotation est une annotation de marqueur qui indique que l'élément (classe, méthode, champ, etc.) est obsolète et a été remplacé par un élément plus récent.
Sa syntaxe est :
@Deprecated
accessModifier returnType deprecatedMethodName() { ... }
Lorsqu'un programme utilise l'élément déclaré obsolète, le compilateur génère un avertissement.
Nous utilisons Javadoc @deprecated
balise pour documenter l'élément obsolète.
/**
* @deprecated
* why it was deprecated
*/
@Deprecated
accessModifier returnType deprecatedMethodName() { ... }
Exemple 1 : Exemple d'annotation @Deprecated
class Main {
/**
* @deprecated
* This method is deprecated and has been replaced by newMethod()
*/
@Deprecated
public static void deprecatedMethod() {
System.out.println("Deprecated method");
}
public static void main(String args[]) {
deprecatedMethod();
}
}
Sortie
Deprecated method
2. @Remplacer
Le @Override
annotation spécifie qu'une méthode d'une sous-classe remplace la méthode de la superclasse avec le même nom de méthode, le même type de retour et la même liste de paramètres.
Il n'est pas obligatoire d'utiliser @Override
lors du remplacement d'une méthode. Cependant, si nous l'utilisons, le compilateur génère une erreur si quelque chose ne va pas (comme un type de paramètre incorrect) lors de la redéfinition de la méthode.
Exemple 2 :exemple d'annotation @Override
class Animal {
// overridden method
public void display(){
System.out.println("I am an animal");
}
}
class Dog extends Animal {
// overriding method
@Override
public void display(){
System.out.println("I am a dog");
}
public void printMessage(){
display();
}
}
class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.printMessage();
}
}
Sortie
I am a dog
Dans cet exemple, en créant un objet dog1 de chien classe, nous pouvons appeler sa méthode printMessage() qui exécute alors le display()
déclaration.
Depuis display()
est défini dans les deux classes, la méthode de la sous-classe Dog remplace la méthode de la superclasse Animal . D'où le display()
de la sous-classe est appelée.
3. @SuppressWarnings
Comme son nom l'indique, le @SuppressWarnings
l'annotation indique au compilateur de supprimer les avertissements générés lors de l'exécution du programme.
Nous pouvons spécifier le type d'avertissements à supprimer. Les avertissements pouvant être supprimés sont spécifiques au compilateur, mais il existe deux catégories d'avertissements :dépréciation et décoché .
Pour supprimer une catégorie particulière d'avertissement, nous utilisons :
@SuppressWarnings("warningCategory")
Par exemple,
@SuppressWarnings("deprecated")
Pour supprimer plusieurs catégories d'avertissements, nous utilisons :
@SuppressWarnings({"warningCategory1", "warningCategory2"})
Par exemple,
@SuppressWarnings({"deprecated", "unchecked"})
Catégorie deprecated
indique au compilateur de supprimer les avertissements lorsque nous utilisons un élément obsolète.
Catégorie unchecked
indique au compilateur de supprimer les avertissements lorsque nous utilisons des types bruts.
Et les avertissements non définis sont ignorés. Par exemple,
@SuppressWarnings("someundefinedwarning")
Exemple 3 :Exemple d'annotation @SuppressWarnings
class Main {
@Deprecated
public static void deprecatedMethod() {
System.out.println("Deprecated method");
}
@SuppressWarnings("deprecated")
public static void main(String args[]) {
Main depObj = new Main();
depObj. deprecatedMethod();
}
}
Sortie
Deprecated method
Ici, deprecatedMethod()
a été marqué comme obsolète et donnera des avertissements au compilateur lorsqu'il sera utilisé. En utilisant le @SuppressWarnings("deprecated")
annotation, nous pouvons éviter les avertissements du compilateur.
4. @SafeVarargs
Le @SafeVarargs
annotation affirme que la méthode ou le constructeur annoté n'effectue pas d'opérations non sécurisées sur ses varargs (nombre variable d'arguments).
Nous ne pouvons utiliser cette annotation que sur des méthodes ou des constructeurs qui ne peuvent pas être remplacés. En effet, les méthodes qui les remplacent peuvent effectuer des opérations non sécurisées.
Avant Java 9, nous pouvions utiliser cette annotation uniquement sur les méthodes finales ou statiques car elles ne peuvent pas être remplacées. Nous pouvons désormais également utiliser cette annotation pour les méthodes privées.
Exemple 4 :Exemple d'annotation @SafeVarargs
import java.util.*;
class Main {
private void displayList(List<String>... lists) {
for (List<String> list : lists) {
System.out.println(list);
}
}
public static void main(String args[]) {
Main obj = new Main();
List<String> universityList = Arrays.asList("Tribhuvan University", "Kathmandu University");
obj.displayList(universityList);
List<String> programmingLanguages = Arrays.asList("Java", "C");
obj.displayList(universityList, programmingLanguages);
}
}
Avertissements
Type safety: Potential heap pollution via varargs parameter lists Type safety: A generic array of List<String> is created for a varargs parameter
Sortie
Note: Main.java uses unchecked or unsafe operations. [Tribhuvan University, Kathmandu University] [Tribhuvan University, Kathmandu University] [Java, C]
Ici, List
... lists
spécifie un argument de longueur variable de type List
. Cela signifie que la méthode displayList()
peut avoir zéro ou plusieurs arguments.
Le programme ci-dessus se compile sans erreur mais donne des avertissements lorsque @SafeVarargs
l'annotation n'est pas utilisée.
Lorsque nous utilisons @SafeVarargs
annotation dans l'exemple ci-dessus,
@SafeVarargs private void displayList(List<String>... lists) { ... }
Nous obtenons la même sortie mais sans aucun avertissement. Les avertissements non cochés sont également supprimés lorsque nous utilisons cette annotation.
5. @InterfaceFonctionnelle
Java 8 a introduit pour la première fois ce @FunctionalInterface
annotation. Cette annotation indique que la déclaration de type sur laquelle elle est utilisée est une interface fonctionnelle. Une interface fonctionnelle ne peut avoir qu'une seule méthode abstraite.
Exemple 5 :Exemple d'annotation @FunctionalInterface
@FunctionalInterface
public interface MyFuncInterface{
public void firstMethod(); // this is an abstract method
}
Si nous ajoutons une autre méthode abstraite, disons
@FunctionalInterface
public interface MyFuncInterface{
public void firstMethod(); // this is an abstract method
public void secondMethod(); // this throws compile error
}
Maintenant, lorsque nous exécutons le programme, nous recevons l'avertissement suivant :
Unexpected @FunctionalInterface annotation @FunctionalInterface ^ MyFuncInterface is not a functional interface multiple non-overriding abstract methods found in interface MyFuncInterface
Il n'est pas obligatoire d'utiliser @FunctionalInterface
annotation. Le compilateur considérera toute interface qui répond à la définition de l'interface fonctionnelle comme une interface fonctionnelle.
Nous utilisons cette annotation pour nous assurer que l'interface fonctionnelle n'a qu'une seule méthode abstraite.
Cependant, il peut avoir n'importe quel nombre de méthodes par défaut et statiques car elles ont une implémentation.
@FunctionalInterface
public interface MyFuncInterface{
public void firstMethod(); // this is an abstract method
default void secondMethod() { ... }
default void thirdMethod() { ... }
}
Annotation personnalisée
Il est également possible de créer nos propres annotations personnalisées.
Sa syntaxe est :
[Access Specifier] @interface<AnnotationName> { DataType <Method Name>() [default value]; }
Voici ce que vous devez savoir sur les annotations personnalisées :
- Les annotations peuvent être créées en utilisant
@interface
suivi du nom de l'annotation. - L'annotation peut avoir des éléments qui ressemblent à des méthodes mais ils n'ont pas d'implémentation.
- La valeur par défaut est facultative. Les paramètres ne peuvent pas avoir une valeur nulle.
- Le type de retour de la méthode peut être une primitive, une énumération, une chaîne, un nom de classe ou un tableau de ces types.
Exemple 6 :Exemple d'annotation personnalisée
@interface MyCustomAnnotation {
String value() default "default value";
}
class Main {
@MyCustomAnnotation(value = "programiz")
public void method1() {
System.out.println("Test method 1");
}
public static void main(String[] args) throws Exception {
Main obj = new Main();
obj.method1();
}
}
Sortie
Test method 1
Méta-annotations
Les méta-annotations sont des annotations qui sont appliquées à d'autres annotations.
1. @Rétention
Le @Retention
annotation spécifie le niveau jusqu'auquel l'annotation sera disponible.
Sa syntaxe est :
@Retention(RetentionPolicy)
Il existe 3 types de règles de conservation :
- RetentionPolicy.SOURCE - L'annotation n'est disponible qu'au niveau de la source et est ignorée par le compilateur.
- RetentionPolicy.CLASS - L'annotation est disponible pour le compilateur au moment de la compilation, mais est ignorée par la machine virtuelle Java (JVM).
- RetentionPolicy.RUNTIME - L'annotation est disponible pour la JVM.
Par exemple,
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation{ ... }
2. @Documenté
Par défaut, les annotations personnalisées ne sont pas incluses dans la documentation Java officielle. Pour inclure notre annotation dans la documentation Javadoc, nous utilisons le @Documented
annotation.
Par exemple,
@Documented
public @interface MyCustomAnnotation{ ... }
3. @Cible
Nous pouvons restreindre l'application d'une annotation à des cibles spécifiques à l'aide du @Target
annotation.
Sa syntaxe est :
@Target(ElementType)
Le ElementType
peut avoir l'un des types suivants :
Type d'élément | Cible |
---|---|
ElementType.ANNOTATION_TYPE | Type d'annotation |
ElementType.CONSTRUCTOR | Constructeurs |
ElementType.FIELD | Champs |
ElementType.LOCAL_VARIABLE | Variables locales |
ElementType.METHOD | Méthodes |
ElementType.PACKAGE | Forfait |
ElementType.PARAMETER | Paramètre |
ElementType.TYPE | Tout élément de classe |
Par exemple,
@Target(ElementType.METHOD)
public @interface MyCustomAnnotation{ ... }
Dans cet exemple, nous avons limité l'utilisation de cette annotation aux méthodes uniquement.
Remarque : Si le type cible n'est pas défini, l'annotation peut être utilisée pour n'importe quel élément.
4. @Hérité
Par défaut, un type d'annotation ne peut pas être hérité d'une superclasse. Cependant, si nous devons hériter d'une annotation d'une superclasse à une sous-classe, nous utilisons le @Inherited
annotation.
Sa syntaxe est :
@Inherited
Par exemple,
@Inherited
public @interface MyCustomAnnotation { ... }
@MyCustomAnnotation
public class ParentClass{ ... }
public class ChildClass extends ParentClass { ... }
5. @Répétable
Une annotation qui a été marquée par @Repeatable
peut être appliqué plusieurs fois à la même déclaration.
@Repeatable(Universities.class)
public @interface University {
String name();
}
La valeur définie dans le @Repeatable
annotation est l'annotation du conteneur. L'annotation de conteneur a une variable valeur de type de tableau de l'annotation répétable ci-dessus. Ici, Universities
sont le type d'annotation contenant.
public @interface Universities {
University[] value();
}
Maintenant, le @University
l'annotation peut être utilisée plusieurs fois sur la même déclaration.
@University(name = "TU")
@University(name = "KU")
private String uniName;
Si nous devons récupérer les données d'annotation, nous pouvons utiliser l'API Reflection.
Pour récupérer les valeurs d'annotation, nous utilisons getAnnotationsByType()
ou getAnnotations()
méthode définie dans l'API Reflection.
Java