Menu
Coddy logo textTech

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 doives créer une classe qui stocke une valeur et la récupère ultérieurement. Sans les 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 du code et des problèmes de 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 maintenant la sécurité des types. Vous définissez un espace réservé (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 un cast
List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0);  // Cast manuel nécessaire

// Avec génériques - type-safe, pas de cast
List<String> list = new ArrayList<String>();
list.add("Hello");
String s = list.get(0);  // Aucun cast nécessaire

Les chevrons <T> désignent un paramètre de type. Lorsque vous écrivez List<String>, vous indiquez au compilateur que cette liste ne contiendra que des chaînes. Si vous essayez d’ajouter un entier, le compilateur détecte immédiatement l’erreur au lieu d’échouer à l’exécution.

Les génériques offrent deux avantages clés : ils éliminent le besoin d’effectuer des 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 propre. Dans les leçons suivantes, nous découvrirons 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 (utilisant Object avec conversion de type) à la nouvelle méthode (utilisant les génériques avec la sécurité des types).

Vous allez créer trois fichiers pour voir directement la différence :

  • OldBox.java : créez une classe qui stocke des valeurs selon la méthode précédant les génériques. Votre OldBox doit avoir un champ privé content de type Object. Incluez un constructeur qui accepte un Object et le stocke, ainsi qu’une méthode getContent() qui renvoie l’Object. Cette approche fonctionne, mais elle nécessite une conversion de type lors de la récupération des valeurs.
  • GenericBox.java : créez maintenant la version moderne, sûre du point de vue des types, en utilisant les génériques. Votre 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, ainsi qu’une méthode getContent() qui renvoie une valeur de type T. Aucune conversion de type n’est nécessaire lors de l’utilisation de cette classe !
  • Main.java : démontrez les deux approches côte à côte. Vous recevrez deux entrées : un mot (String) et un nombre (entier).

    Commencez par utiliser l’ancienne approche : créez un OldBox qui stocke le mot, puis récupérez-le avec une conversion en String et affichez : OldBox (with cast): [value]

    Ensuite, utilisez l’approche générique : créez un GenericBox<String> qui stocke le même mot, récupérez-le sans conversion et affichez : GenericBox (no cast): [value]

    Montrez ensuite que les génériques fonctionnent avec les entiers : créez un GenericBox<Integer> qui stocke le nombre, récupérez-le et affichez : GenericBox Integer: [value]

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

Vous recevrez deux entrées dans l’ordre : un mot (String) et un nombre (entier sous forme de String, que vous analyserez).

Remarquez la différence essentielle : avec OldBox, vous devez effectuer la conversion (String) box.getContent() et espérer avoir obtenu le bon type. Avec GenericBox, le compilateur connaît le type et aucune conversion n’est nécessaire. C’est le principal avantage des génériques : la sécurité des types sans les complications liées aux conversions !

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 stockant le mot
        // Retrieve with cast to String and print: "OldBox (with cast): [value]"
        
        // TODO: Créer une GenericBox<String> stockant le mot
        // Retrieve without casting and print: "GenericBox (no cast): [value]"
        
        // TODO: Create a GenericBox<Integer> storing the number
        // Retrieve and print: "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