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.

Imaginez que vous deviez créer une classe qui stocke une valeur et la récupère plus tard. Sans les génériques, vous devriez é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é de type. Vous définissez un espace réservé (appelé un 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 transtypage (casting)
List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0);  // Transtypage manuel nécessaire

// Avec les génériques - type sécurisé, pas de transtypage
List<String> list = new ArrayList<String>();
list.add("Hello");
String s = list.get(0);  // Pas de transtypage 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 de caractères. Si vous essayez d'ajouter un entier, le compilateur détecte l'erreur immédiatement plutôt que d'échouer au moment de l'exécution.

Les génériques offrent deux avantages clés : ils éliminent le besoin de transtypage explicite et ils détectent les erreurs de type au moment de la compilation plutôt qu'à l'exécution. Cela rend votre code à la fois plus sûr et plus propre. Dans les leçons suivantes, nous explorerons 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) par rapport à la nouvelle méthode (utilisation des génériques avec sécurité de type).

Vous allez créer trois fichiers pour voir la différence par vous-même :

  • OldBox.java : Créez une classe qui stocke des valeurs à la manière d'avant 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 retourne l'Object. Cette approche fonctionne mais nécessite un transtypage (casting) lors de la récupération des valeurs.
  • GenericBox.java : Créez maintenant la version moderne et sûre au niveau des types en utilisant les génériques. Votre GenericBox doit utiliser un paramètre de type T dans sa déclaration. Elle a besoin d'un champ privé content de type T, d'un constructeur qui accepte une valeur T, et d'une méthode getContent() qui retourne le type T. Aucun transtypage 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 (integer).

    Tout d'abord, utilisez l'ancienne approche : créez une OldBox stockant le mot, puis récupérez-le avec un transtypage en String et affichez : OldBox (with cast): [value]

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

    Ensuite, montrez les génériques fonctionnant avec des entiers : créez un GenericBox<Integer> stockant 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 devrez analyser).

Remarquez la différence clé : avec OldBox, vous devez transtyper (String) box.getContent() et espérer que vous avez le bon type. Avec GenericBox, le compilateur connaît le type et aucun transtypage n'est nécessaire. C'est l'avantage fondamental des génériques : la sécurité de type sans les tracas du transtypage !

Aide-mémoire

Les génériques vous permettent d'écrire des classes et des méthodes qui fonctionnent avec n'importe quel type tout en maintenant la sécurité de typage. Ils utilisent des paramètres de type (placeholders) qui sont remplacés par des types réels lorsque la classe est utilisée.

Sans les génériques (en utilisant Object) :

List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0);  // Manual casting required

Avec les génériques (type-safe) :

List<String> list = new ArrayList<String>();
list.add("Hello");
String s = list.get(0);  // No casting needed

Créer une classe générique :

public class GenericBox<T> {
    private T content;
    
    public GenericBox(T content) {
        this.content = content;
    }
    
    public T getContent() {
        return content;
    }
}

Utiliser une classe générique :

GenericBox<String> stringBox = new GenericBox<String>("Hello");
String value = stringBox.getContent();  // No casting

GenericBox<Integer> intBox = new GenericBox<Integer>(42);
Integer number = intBox.getContent();  // Type-safe

Les chevrons <T> désignent un paramètre de type. Les avantages incluent : aucun transtypage (casting) explicite n'est nécessaire et les erreurs de type sont détectées à la compilation plutôt qu'à l'exécution.

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 un OldBox stockant le word
        // Récupérer avec un cast vers String et afficher : "OldBox (with cast): [value]"
        
        // TODO: Créer un GenericBox<String> stockant le word
        // Récupérer sans cast et afficher : "GenericBox (no cast): [value]"
        
        // TODO: Créer un GenericBox<Integer> stockant le number
        // 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