La généricité permet de différer la spécification des types jusqu'à l'instantiation ou l'invocation. Elle transforme les types en véritables paramètres, offrant ainsi une sécurité à la compilation sans sacrifier la flexibilité. Seuls les types référance sont admissibles — les primitives restent exclues.
Classes et interfaces paramétrées
Une classe générique déclare ses paramètres de type entre chevrons après son nom. Ces identificateurs servent ensuite de types conventionnels dans le corps de la classe.
Déclaration
public class Conteneur<V> {
// V agit comme un type quelconque
}
Exploitation du paramètre
public class Conteneur<V> {
public void stocker(V element) {
// manipulation de l'élément
}
}
Résolution du type
Via l'instanciation :
public static void main(String[] args) {
Conteneur<String> c = new Conteneur<>();
c.stocker("exemple");
}
Via l'héritage :
public class BoiteTexte extends Conteneur<String> {
@Override
public void stocker(String element) {
// le type est fixé définitivement
}
}
Il est également possible de propager le paramètre dans la chaîne d'héritage :
public class BoiteGenerique<V> extends Conteneur<V> {
@Override
public void stocker(V element) {
super.stocker(element);
}
}
Méthodes paramétrées
Contrairement aux classes, une méthode générique porte ses propres paramètres de type, déclarés avant le type de retour.
Déclaration et utilisation
public static <R> R traiter(R entree) {
return entree;
}
Déduction automatique
public static void main(String[] args) {
Integer nombre = traiter(42);
String chaine = traiter("autre");
}
Limitation des bornes
Les jokers bornés restreignent l'unievrs des types acceptables selon deux modalités complémentaires.
Borne supérieure
Le type accepté doit être le type cible ou un sous-type.
public void afficher(List<? extends Animal> creatures) {
// Lecture sécurisée, insertion interdite
}
Borne inférieure
Le type excepté doit être le type cible ou un super-type.
public void enregistrer(List<? super Chat> emplacements) {
// Insertion possible, lecture retournant Object
}
Contraintes d'application
| Notation | Classes et interfaces | Paramètres de méthode |
|---|---|---|
| <T extends X> | Applicable | Applicable |
| <? super X> | Non applicable | Applicable |
La borne supérieure sert couramment pour la lecture de collections, tandis que la borne inférieure facilite l'écriture dans des structures de type producteur-consommateur.