Menu
CoddyTech

Introduction à la généricité

Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy. Leçon 53 sur 87.

Imagine que tu dois créer une classe qui stocke une valeur et la récupère plus tard. Sans les types génériques, tu devrais écrire des classes distinctes pour chaque type : une pour Integer, une pour String, une pour Double, et ainsi de suite. Cela entraîne une duplication de code et complique la maintenance.

Les génériques résolvent ce problème en vous permettant d’écrire des classes et des méthodes qui fonctionnent avec n’importe quel type, tout en garantissant la sécurité des types. Vous définissez un paramètre fictif (appelé paramètre de type) qui est remplacé par un type réel lorsque vous utilisez la classe :

// Sans génériques - utilise Object, nécessite une conversion de type
List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0);  // Conversion de type manuelle nécessaire

// Avec les génériques - typage sûr, sans conversion de type
List<String> list = new ArrayList<String>();
list.add("Hello");
String s = list.get(0);  // Aucune conversion de type nécessaire

Les chevrons <T> désignent un paramètre de type. Lorsque tu écris List<String>, tu indiques au compilateur que cette liste ne contiendra que des chaînes de caractères. Si tu essaies d’y ajouter un entier, le compilateur détecte immédiatement l’erreur au lieu de la laisser se produire à l’exécution.

Les génériques offrent deux avantages clés : ils éliminent le besoin de conversions de type explicites et détectent les erreurs de type à la compilation plutôt qu’à l’exécution. Votre code est ainsi à la fois plus sûr et plus lisible. Dans les leçons suivantes, nous verrons comment créer vos propres classes et méthodes génériques.

challenge icon

Défi

Facile

Construisons un système de stockage simple qui démontre la puissance des génériques en comparant l’ancienne méthode (utilisation de Object avec transtypage) à la nouvelle (utilisation des génériques avec sécurité de types).

Tu vas créer trois fichiers pour constater la différence par toi-même :

  • OldBox.java : crée une classe qui stocke des valeurs selon la méthode d’avant les génériques. Ta classe OldBox doit avoir un champ privé content de type Object. Ajoute un constructeur qui accepte un Object et le stocke, ainsi qu’une méthode getContent() qui renvoie l’Object. Cette méthode fonctionne, mais nécessite un transtypage lors de la récupération des valeurs.
  • GenericBox.java : crée maintenant la version moderne avec sécurité de types, en utilisant les génériques. Ta classe GenericBox doit utiliser un paramètre de type T dans sa déclaration. Elle doit avoir un champ privé content de type T, un constructeur qui accepte une valeur de type T et une méthode getContent() qui renvoie le type T. Aucun transtypage n’est nécessaire avec cette classe !
  • Main.java : montre les deux méthodes côte à côte. Tu recevras deux entrées : un mot (String) et un nombre (entier).

    D’abord, utilise l’ancienne méthode : crée un OldBox qui stocke le mot, puis récupère-le avec un transtypage en String et affiche : OldBox (with cast): [value]

    Ensuite, utilise la méthode générique : crée un GenericBox<String> qui stocke le même mot, récupère-le sans transtypage et affiche : GenericBox (no cast): [value]

    Montre ensuite comment les génériques fonctionnent avec des entiers : crée un GenericBox<Integer> qui stocke le nombre, récupère-le et affiche : GenericBox Integer: [value]

    Enfin, affiche une ligne vide suivie de : Type safety: Generics catch errors at compile time!

Tu recevras deux entrées dans l’ordre suivant : un mot (String), puis un nombre (un entier sous forme de String, que tu analyseras).

Remarque la différence essentielle : avec OldBox, tu dois effectuer le transtypage (String) box.getContent() et espérer avoir obtenu le bon type. Avec GenericBox, le compilateur connaît le type et aucun transtypage n’est nécessaire. C’est le principal avantage des génériques : la sécurité de types sans les contraintes du transtypage !

Essayez vous-même

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String word = scanner.nextLine();
        int number = Integer.parseInt(scanner.nextLine());
        
        // TODO: Créer une OldBox contenant le mot
        // Récupérer en effectuant une conversion de type vers String et afficher : "OldBox (with cast): [value]"
        
        // TODO: Créer une GenericBox<String> contenant le mot
        // Récupérer sans conversion de type et afficher : "GenericBox (no cast): [value]"
        
        // TODO: Créer une GenericBox<Integer> contenant le nombre
        // Récupérer et afficher : "GenericBox Integer: [value]"
        
        // TODO: Afficher une ligne vide, puis afficher :
        // "Type safety: Generics catch errors at compile time!"
    }
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Java en ligne