Un type générique est une classe ou une interface générique qui est paramétrée sur des types. La classe Box suivante sera modifiée pour illustrer le concept.
Une classe Box simple
Commencez par examiner une classe Box non générique qui opère sur des objets de tout type. Il lui suffit de fournir deux méthodes: set, qui ajoute un objet à la boîte, et get, qui le récupère:
Puisque ses méthodes acceptent ou retournent un objet, vous êtes libre de passer ce que vous voulez , à condition qu’il ne fasse pas partie des types primitifs. Il n’y a aucun moyen de vérifier, au moment de la compilation, comment la classe est utilisée. Une partie du code peut placer un entier dans la boîte et s’attendre à en extraire des nombres entiers, tandis qu’une autre partie du code peut passer par erreur une chaîne, entraînant une erreur d’exécution.
Une version générique de la classe Box
Une classe générique est définie au format suivant:
class name<T1, T2, ..., Tn> { /* ... */ }
Pour mettre à jour le Classe Box pour utiliser des génériques, vous créez une déclaration de type générique en remplaçant le code « public class Box » par « public class Box < T > « . Ceci introduit la variable de type, T, qui peut être utilisée n’importe où dans la classe.
Avec ce changement, la classe Box devient:
Comme vous pouvez le voir, toutes les occurrences d’Object sont remplacée par T. Une variable de type peut être n’importe quel type non primitif que vous spécifiez: n’importe quel type de classe, n’importe quel type d’interface, n’importe quel type de tableau, ou même une autre variable de type.
Cette même technique peut être appliquée pour créer interfaces génériques.
Conventions de dénomination des paramètres de type
Par convention, les noms de paramètres de type sont des lettres majuscules simples. Cela contraste fortement avec les conventions de dénomination des variables que vous connaissez déjà, et pour une bonne raison: sans cette convention, il serait difficile de faire la différence entre une variable de type et un nom de classe ou d’interface ordinaire.
Les noms de paramètres de type les plus couramment utilisés sont:
- E – Element (largement utilisé par Java Collections Framework)
- K – Key
- N – Nombre
- T – Type
- V – Valeur
- S, U, V etc. – 2ème, 3ème, 4ème types
Vous verrez ces noms utilisés dans l’API Java SE et dans le reste de cette leçon.
Appel et instanciation d’un type générique
Pour référencer la classe générique Box à partir de votre code, vous devez effectuer un appel de type générique, qui remplace T par une valeur concrète, telle que Integer:
Box<Integer> integerBox;
Vous pouvez considérer une invocation de type générique comme étant similaire à une invocation de méthode ordinaire, mais au lieu de passer un argument à am méthode, vous passez un argument de type – Integer dans ce cas – à la classe Box elle-même.
Comme toute autre déclaration de variable, ce code ne crée pas réellement un nouvel objet Box. Il déclare simplement que integerBox contiendra une référence à une « Box of Integer », c’est ainsi que Box < Integer > est lu.
Un appel d’un type générique est généralement appelé type paramétré.
Pour instancier cette classe, utilisez le mot-clé new, comme d’habitude, mais placez < Entier > entre le nom de la classe et les parenthèses:
Box<Integer> integerBox = new Box<Integer>();
Le diamant
Dans Java SE 7 et versions ultérieures, vous pouvez remplacer les arguments de type requis pour appeler le constructeur d’une classe générique par un ensemble vide d’arguments de type (< >) tant que le compilateur peut déterminer ou déduire les arguments de type à partir du contexte. Cette paire de crochets angulaires, < >, est officieusement appelée le diamant. Par exemple, vous pouvez créer une instance de Box < Integer > avec l’instruction suivante:
Box<Integer> integerBox = new Box<>();
Pour plus d’informations sur la notation en losange et l’inférence de type, voir Inférence de type.
Paramètres de type multiples
Comme mentionné précédemment, une classe générique peut avoir plusieurs paramètres de type.Par exemple, la classe générique OrderedPair, qui implémente l’interface générique Pair:
Les instructions suivantes créent deux instanciations de la classe OrderedPair:
Le code, new OrderedPair < String, Integer >, instancie K en tant que String et V en tant qu’Integer. Par conséquent, les types de paramètres du constructeur de OrderedPair sont respectivement String et Integer. En raison de l’autoboxing, il est valide de passer un String et un int à la classe.
Comme mentionné dans The Diamond, Le compilateur Java peut déduire les types K et V à partir de la déclaration OrderedPair < String, Integer >, ces instructions peuvent être raccourcies en utilisant la notation en losange:
OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);OrderedPair<String, String> p2 = new OrderedPair<>("hello", "world");
Pour créer une interface générique, suivez les mêmes conventions que pour créer une classe générique.
Types paramétrés
OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));