Généricité en Java : maîtriser les types paramétrés

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.

Étiquettes: Java Generics Type Parameters Wildcards Bounded Types

Publié le 19 octobre à 13h23