Programmation Java/Types génériques
Définition.
Les génériques (de l'anglais "generics") sont des classes qui sont typés au moment de la compilation. Autrement dit, ce sont des classes qui utilisent des typages en paramètres. Ainsi une liste chainée, qui peut contenir des entiers, des chaines ou autres, pourra être typée en liste de chaines ou liste d'entiers, et ceci permettra au programmeur de ne pas écrire systématiquement des transtypages, méthode qui pourrait s'avérer dangereuse, ce sera le compilateur qui vérifiera la cohérence des données.
Java 5 a introduit un principe de type générique, rappelant les "templates" (modèles) du C++, mais le code produit est unique pour tous les objets obtenus à partir de la même classe générique.
Avant Java 5 :
public class MaListe
 private LinkedList liste;
 public setMembre(String s)
 liste.add(s);
 public int getMembre(int i)
 return (Int)liste.get(i);
Le transtypage est obligatoire, LinkedList manipule des objets Object, ici le compilateur ne peut détecter de problème, problème qui ne surviendra qu'à l'exécution (RunTimeError).
Dans la version avec génériques, on n'a plus besoin d'utiliser le transtypage donc le compilateur déclenchera deux erreurs durant la compilation, une sur la méthode, l'autre sur l'ajout d'un entier.
public class Famille < MaClasse >
 private LinkedList < MaClasse > liste;
 public setMembre(MaClasse m)
 liste.add(m);
 public MaClasse getMembre(int i)
 return liste.get(i);
 public Integer getInt(int i) //première erreur
 return liste.get(i);
Utilisation :
Famille<String> famille = new Famille<String>();
famille.setMembre("essai");
famille.setMembre(210); //seconde erreur
Il est important de comprendre que dans la déclaration de la classe le paramètre placé entre les caractères < et > représente bien une classe qui ne sera déterminée que lors de la déclaration de la création de l'objet. Aussi une erreur de typage sera produite à la compilation si les types utilisés par les méthodes ne sont le ou les types attendus. Dans cet exemple, l'erreur sera signalée sur le second ajout.
Dans la déclaration de la classe, la liste membre est déclarée ne pouvant contenir que des objets de classe MaClasse. L'identifiant MaClasse n'est pas une classe existante dans le packages et il est préférable qu'il ne le soit pas pour qu'aucune confusion ne soit faite, c'est à la déclaration de l'objet Famille que l'identifiant MaClasse sera résolu.
Il est évidemment possible d'utiliser un objet d'une classe héritant de celle utilisée pour paramétrer le type générique. Ceci permet de plus d'assurer la compatibilité ascendante avec les versions antérieures de Java : si aucune classe de paramétrage n'est indiquée, la classe par défaut est codice_1.
Plusieurs paramètres.
De la même façon que pour les classes basées sur les List, les déclarations de vos classes peuvent utiliser ces génériques. Cela permet de rendre le code plus souple et surtout réutilisable dans des contextes très différents. Plusieurs paramètres, séparés par des virgules, peuvent être utilisés entre les caractères < et >.
public class ListeDeTruc<Truc, Bidule>
 private LinkedList <Truc> liste = new LinkedList<>();
 private ArrayList <Bidule> tableau = new ArrayList<>();
 public void accumule(Truc m)
 liste.add(m);
 public Bidule recherche(int i)
 return tableau.get(i);
Déclaration possible :
ListeDeTruc<String,Integer> liste1 = new ListeDeTruc<String,Integer>();
ListeDeTruc<Thread,Date> liste2 = new ListeDeTruc<Thread,Date>();
Paramètres non spécifiés à l'initialisation.
Dans la classe de la section précédente, la création des deux collections avec l'opérateur codice_2 s'effectue avec une liste de paramètres génériques vide codice_3 juste après le nom des classes génériques :
private LinkedList <Truc> liste = new LinkedList<>();
private ArrayList <Bidule> tableau = new ArrayList<>();
Cette syntaxe (supportée depuis Java 8) indique que les paramètres sont les mêmes que ceux de la déclaration des membres.
Cela équivaut à ceci :
private LinkedList <Truc> liste = new LinkedList<Truc>();
private ArrayList <Bidule> tableau = new ArrayList<Bidule>();
Les paramètres ne sont cependant pas toujours identiques à ceux de la déclaration : il est possible par exemple d'utiliser des sous-classes.
Génériques et héritages.
Lorsqu'un type de base doit répondre à des spécifications précises, il est possible d'écrire des choses du genre :
 public class ListeDeTruc<Truc extends Bidule, MaList<String» implements Moninterface<Chose>
En revanche, créer une classe qui hérite de ces objets est plus délicat. Ici Chose et Bidule sont des classes existantes, Truc ne sera résolu qu'au moment de la déclaration de l'objet ListeDeTruc. 
L'utilisation du mot clef super est possible dans une classe héritant d'une classe générique.
Tableau de génériques.
La déclaration d'un tableau d'objets dont le type est générique peut se faire sans déclencher ni erreur, ni avertissements et sans utiliser l'annotation codice_4, en utilisant codice_5 :
ArrayList<?>[] namelists = new ArrayList<?>[5];
Compatibilité entre les types.
La relation d'héritage entre classe pour le type générique ne rend pas les classes compatibles.
La compatibilité est illustré ci-dessous, où la classe codice_6 hérite de la classe codice_7 et la classe codice_8 hérite de la classe codice_9 :
Exemple :
List<Cat> les_chats_du_voisinage = /* ... */;
List<? extends Cat> list_1 = les_chats_du_voisinage; // OK
Collection<Cat> list_2 = les_chats_du_voisinage; // OK
Collection<? extends Animal> list_3 = les_chats_du_voisinage; // OK
List<Animal> list_4 = les_chats_du_voisinage; // ERROR
Conventions sur les noms des types.
Bien qu'il soit tout à fait possible d'utiliser n'importe-quel identifiant suivant la convention de nommage des classes, il est plutôt recommandé d'utiliser un identifiant composé d'une seule lettre selon la convention :
Limitations.
Malgré la similitude de syntaxe, les types génériques en Java sont différents des patrons ("templates" en anglais) du C++.
Il faut plutôt les voir comme un moyen d'éviter de faire une conversion entre java.lang.Object et le type spécifié de manière implicite.
Parmi les limitations :