Didacticiel d’exemple Java Generics – Méthode générique, classe, interface
Java Genrics est l’une des fonctionnalités les plus importantes introduites dans Java 5.
Si vous avez travaillé sur des collections Java et avec la version 5 ou supérieure, je suis sûr que vous l’avez utilisée.
Les génériques en Java avec des classes de collection sont très faciles, mais ils fournissent beaucoup plus de fonctionnalités que la simple création du type de collection.
Nous allons essayer d’apprendre les fonctionnalités des génériques dans cet article. Comprendre les génériques peut parfois devenir déroutant si nous utilisons des mots de jargon, j’essaierais donc de rester simple et facile à comprendre.
Génériques en Java
Des génériques ont été ajoutés dans Java 5 pour fournir une vérification de type à la compilation et supprimer le risque de ClassCastException
qui était courant pendant le travail avec des classes de collection. L’ensemble du cadre de collecte a été réécrit pour utiliser des génériques pour la sécurité de type. Voyons comment les génériques nous aident à utiliser les classes de collection en toute sécurité.
Le code ci-dessus se compile correctement mais lance une exception ClassCastException au moment de l’exécution, car nous essayons de convertir Object de la liste en String alors que l’un des éléments est de type Integer. Après Java 5, nous utilisons des classes de collection comme ci-dessous.
Notez qu’au moment de la création de la liste, nous avons spécifié que le type d’éléments de la liste sera String. Donc, si nous essayons d’ajouter tout autre type d’objet dans la liste, le programme lancera une erreur de compilation. Notez également que dans la boucle for, nous n’avons pas besoin de transtypage de l’élément dans la liste, d’où la suppression de l’exception ClassCastException à l’exécution.
Classe générique Java
Nous pouvons définir nos propres classes avec le type générique. Un type générique est une classe ou une interface qui est paramétrée sur des types. Nous utilisons des chevrons (< >) pour spécifier le paramètre de type.
Pour comprendre l’avantage, disons nous avons une classe simple comme:
Notez que lors de l’utilisation de cette classe, nous devons utiliser la conversion de type et elle peut produire ClassCastException au moment de l’exécution. Nous allons maintenant utiliser la classe générique java pour réécrire la même classe comme indiqué ci-dessous.
Notez l’utilisation de la classe GenericsType dans la méthode main. Nous n’avons pas besoin d’effectuer de conversion de type et nous pouvons supprimer ClassCastException au moment de l’exécution. Si nous ne fournissons pas le type au moment de la création, le compilateur produira un avertissement indiquant que « GenericsType est un type brut.
Références au type générique GenericsType < T > doit être paramétré ». Lorsque nous ne fournissons pas le type, le type devient Object
et permet donc les deux String et les objets Integer. Mais, nous devrions toujours essayer d’éviter cela car nous devrons utiliser la conversion de type tout en travaillant sur un type brut qui peut produire des erreurs d’exécution.
@SuppressWarnings("rawtypes")
annotation pour supprimer l’avertissement du compilateur, consultez le didacticiel sur les annotations java. Notez également qu’il prend en charge la mise en boîte automatique Java.
Interface générique Java
L’interface comparable est un excellent exemple de Generics dans les interfaces et elle s’écrit:
De la même manière, nous pouvons créer des interfaces génériques en java. Nous pouvons également ont plusieurs paramètres de type comme dans l’interface de la carte. gain, nous pouvons également fournir une valeur paramétrée à un type paramétré, par exemple new HashMap<String, List<String>>();
est valide.
Type générique Java
Nommage de type générique Java convention nous aide à comprendre le code facilement et avoir une convention de dénomination est l’une des meilleures pratiques du langage de programmation Java. Les génériques ont donc également leurs propres conventions de dénomination. Habituellement, les noms des paramètres de type sont des lettres majuscules uniques pour les distinguer facilement des variables java. Les noms de paramètres de type les plus couramment utilisés sont:
- E – Element (largement utilisé par Java Collections Framework, par exemple ArrayList, Set, etc.)
- K – Key ( Utilisé dans la carte)
- N – Nombre
- T – Type
- V – Valeur (utilisé dans la carte)
- S, U, V etc. – 2ème, 3ème, 4ème types
Méthode générique Java
Parfois, nous ne voulons pas que toute la classe soit paramétrée, dans ce cas, nous pouvons créer la méthode java generics. Puisque le constructeur est un type particulier de méthode, nous pouvons également utiliser le type générique dans les constructeurs.
Voici une classe montrant un exemple de méthode générique java.
Notez la méthode isEqual signature montrant la syntaxe pour utiliser le type générique dans les méthodes. Notez également comment utiliser ces méthodes dans notre programme java. Nous pouvons spécifier le type en appelant ces méthodes ou nous pouvons les invoquer comme une méthode normale. Le compilateur Java est suffisamment intelligent pour déterminer le type de variable à utiliser, cette fonctionnalité est appelée inférence de type.
Paramètres de type borné Java Generics
Supposons que nous voulions restreindre le type d’objets qui peuvent être utilisés dans le type paramétré, par exemple dans une méthode qui compare deux objets et que nous voulons assurez-vous que les objets acceptés sont comparables. Pour déclarer un paramètre de type borné, indiquez le nom du paramètre de type, suivi du mot-clé extend, suivi de sa limite supérieure, similaire à la méthode ci-dessous.
Le l’invocation de ces méthodes est similaire à la méthode illimitée sauf que si nous essayons d’utiliser une classe qui n’est pas comparable, cela générera une erreur de compilation.
Les paramètres de type borné peuvent être utilisés avec des méthodes ainsi que classes et interfaces.
Java Generics prend également en charge plusieurs limites, c’est-à-dire < T étend A & B & C >. Dans ce cas, A peut être une interface ou une classe. Si A est une classe, B et C devraient être une interface. Nous ne pouvons pas avoir plus d’une classe dans plusieurs limites.
Génériques Java et héritage
Nous savons que L’héritage Java nous permet d’assigner une variable A à une autre variable B si A est une sous-classe de B. On pourrait donc penser que n’importe quel type générique de A peut être affecté au type générique de B, mais ce n’est pas le cas. Voyons cela avec un programme simple.
Nous ne sommes pas autorisés à attribuer la variable MyClass < String > à MyClass < Object > variable car ils ne sont pas liés, en fait MyClass < T > parent est Object.
Classes génériques Java et sous-typage
Nous pouvons sous-saisir une classe ou une interface générique en l’étendant ou en l’implémentant. La relation entre les paramètres de type d’une classe ou d’une interface et les paramètres de type d’une autre est déterminée par les clauses extend et implements.
La relation de sous-typage est préservée tant que nous ne changeons pas l’argument de type, ci-dessous montre un exemple de plusieurs paramètres de type.
Les sous-types de List < String > peut être MaListe < Chaîne, Objet >, MaListe < String, Integer > et ainsi de suite.
Jokers génériques Java
Le point d’interrogation (?) Est le joker dans les génériques et représente un type inconnu. Le caractère générique peut être utilisé comme type de paramètre, champ ou variable locale et parfois comme type de retour. Nous ne pouvons pas utiliser de caractères génériques lors de l’appel d’une méthode générique ou de l’instanciation d’une classe générique. Dans les sections suivantes, nous en apprendrons davantage sur les caractères génériques de limite supérieure, les caractères génériques de limite inférieure et la capture de caractères génériques.
9.1) Java Generics Upper Bounded Wildcard
Les caractères génériques de limite supérieure sont utilisés pour assouplir le restriction sur le type de variable dans une méthode. Supposons que nous voulions écrire une méthode qui retournera la somme des nombres dans la liste, donc notre implémentation sera quelque chose comme ceci.
Maintenant, le problème avec ci-dessus est qu’il ne fonctionnera pas avec la liste des entiers ou des doubles car nous savons que la liste < Integer > et la liste < Les doubles > ne sont pas liés, c’est à ce moment qu’un caractère générique à limite supérieure est utile. Nous utilisons le caractère générique générique avec le mot clé extend et la classe ou l’interface de la limite supérieure qui nous permettront de passer l’argument de la limite supérieure ou de ses types de sous-classes.
L’implémentation ci-dessus peut être modifiée comme le programme ci-dessous. >
C’est similaire à l’écriture de notre code en termes d’interface, dans la méthode ci-dessus, nous pouvons utiliser toutes les méthodes de la classe supérieure Number. Notez qu’avec la liste bornée supérieure, nous ne sommes pas autorisés à ajouter un objet à la liste sauf null. Si nous essayons d’ajouter un élément à la liste dans la méthode sum, le programme ne compilera pas.
9.2) Java Generics Unbounded Wildcard
Parfois, nous avons une situation où nous veulent que notre méthode générique fonctionne avec tous les types, dans ce cas, un caractère générique illimité peut être utilisé. C’est la même chose que d’utiliser <? étend l’objet >.
Nous pouvons fournir la liste < Chaîne > ou List < Integer > ou tout autre type d’argument de liste d’objets pour le printData méthode. Semblable à la liste de limite supérieure, nous ne sommes pas autorisés à ajouter quoi que ce soit à la liste.
9.3) Java Generics Joker à limite inférieure
Supposons que nous voulions ajouter des entiers à une liste d’entiers dans une méthode, nous pouvons conserver le type d’argument comme List < Integer > mais il sera lié avec des nombres entiers alors que List < Number > et List < L’objet > peut également contenir des entiers, nous pouvons donc utiliser un caractère générique de limite inférieure pour y parvenir. Nous utilisons des génériques génériques (?) Avec un super mot-clé et une classe de limite inférieure pour y parvenir.
Nous pouvons passer une borne inférieure ou n’importe quel supertype de borne inférieure en argument, dans ce cas, le compilateur java permet d’ajouter une borne inférieure les types d’objets liés à la liste.
Sous-typage à l’aide de Generics Wildcard
Effacement de type Java Generics
Génériques dans Java a été ajouté pour fournir une vérification de type au moment de la compilation et il n’a aucune utilité au moment de l’exécution, donc le compilateur java utilise la fonction d’effacement de type pour supprimer tout le code de vérification de type générique dans le code d’octet et insérer la conversion de type si nécessaire. L’effacement de type garantit qu’aucune nouvelle classe n’est créée pour les types paramétrés; par conséquent, les génériques n’entraînent aucune surcharge d’exécution.
Par exemple, si nous avons une classe générique comme ci-dessous;
Le compilateur Java remplace le paramètre de type borné T par la première interface liée, Comparable , comme ci-dessous le code:
FAQ sur les génériques
12.1) Pourquoi utilisons-nous les génériques en Java?
Les génériques fournissent une vérification de type forte lors de la compilation et réduisent le risque de ClassCastException et conversion explicite des objets.
12.2) Qu’est-ce que T dans les génériques?
Nous utilisons < T > pour créer une classe, une interface et une méthode génériques. Le T est remplacé par le type réel lorsque nous l’utilisons.
12.3) Comment fonctionne Generics en Java?
Le code générique assure la sécurité du type. Le compilateur utilise l’effacement de type pour supprimer tous les paramètres de type au moment de la compilation afin de réduire la surcharge à l’exécution.
Génériques en Java – Lectures supplémentaires
C’est tout pour les génériques en java, java les génériques sont un sujet très vaste et nécessitent beaucoup de temps pour les comprendre et les utiliser efficacement. Cet article tente de fournir des détails de base sur les génériques et comment pouvons-nous l’utiliser pour étendre notre programme avec type-safety.