Méthodes génériques
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 55 sur 87.
Alors que les classes génériques permettent à des classes entières de fonctionner avec différents types, il arrive parfois que seule une méthode doive être générique. Une méthode générique déclare son propre paramètre de type, indépendamment de tout générique au niveau de la classe.
Le paramètre de type apparaît avant le type de retour dans la signature de la méthode :
public class Utility {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
}
String[] names = {"Alice", "Bob"};
Integer[] numbers = {1, 2, 3};
Utility.printArray(names); // Fonctionne avec String[]
Utility.printArray(numbers); // Fonctionne avec Integer[]Remarquez le <T> placé entre les modificateurs et le type de retour. Cela déclare T comme un paramètre de type pour cette méthode spécifique. Le compilateur déduit le type réel à partir des arguments que vous passez.
Les méthodes génériques peuvent également retourner le type générique :
public static <T> T getFirst(T[] array) {
if (array.length > 0) {
return array[0];
}
return null;
}
String first = getFirst(new String[]{"a", "b"}); // Retourne "a"Vous pouvez utiliser plusieurs paramètres de type si nécessaire :
public static <K, V> void printPair(K key, V value) {
System.out.println(key + ": " + value);
}
printPair("Age", 25); // String et Integer
printPair(1, "First"); // Integer et StringLes méthodes génériques sont particulièrement utiles dans les classes utilitaires où vous avez besoin d'opérations flexibles et réutilisables sans créer de classe générique.
Défi
FacileConstruisons une boîte à outils utilitaire qui met en valeur la flexibilité des méthodes génériques. Vous allez créer une classe avec des méthodes réutilisables qui fonctionnent avec n'importe quel type, démontrant ainsi comment les méthodes génériques peuvent exister indépendamment des classes génériques.
Vous organiserez votre code sur deux fichiers :
ArrayUtils.java: Créez une classe utilitaire contenant des méthodes génériques pour travailler avec des tableaux. Votre classe doit avoir trois méthodes génériques statiques :getLast- Une méthode générique qui prend un tableau de typeTet retourne le dernier élément. Si le tableau est vide, retourneznull.swap- Une méthode générique qui prend un tableau de typeTet deux indices entiers, puis échange les éléments à ces positions. Cette méthode ne retourne rien.printWithLabel- Une méthode générique avec deux paramètres de typeKetV. Elle prend une étiquette de typeKet une valeur de typeV, puis les affiche au format :[label]: [value]Main.java: Mettez vos méthodes génériques au travail ! Vous recevrez quatre entrées : deux mots (Strings) et deux nombres (entiers).Tout d'abord, créez un tableau
String[]contenant les deux mots. UtilisezgetLastpour obtenir le dernier élément et affichez :Last word: [result]Ensuite, créez un tableau
Integer[]contenant les deux nombres. Appelezswappour échanger les éléments aux indices 0 et 1, puis affichez :After swap: [first], [second]Enfin, démontrez la méthode générique à deux paramètres en appelant
printWithLabeldeux fois :- Une fois avec le premier mot comme étiquette et le premier nombre comme valeur
- Une fois avec le premier nombre comme étiquette et le deuxième mot comme valeur
Vous recevrez quatre entrées dans l'ordre : premier mot, deuxième mot, premier nombre, deuxième nombre.
Remarquez comment chaque méthode déclare son ou ses propres paramètres de type avec <T> ou <K, V> avant le type de retour. Le compilateur déduit les types réels à partir des arguments que vous passez — pas besoin de les spécifier explicitement lors de l'appel des méthodes !
Aide-mémoire
Une méthode générique déclare son propre paramètre de type, indépendamment de tout générique au niveau de la classe. Le paramètre de type apparaît avant le type de retour dans la signature de la méthode.
Syntaxe de base d'une méthode générique :
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}Le <T> est placé entre les modificateurs et le type de retour. Le compilateur déduit le type réel à partir des arguments que vous passez.
Les méthodes génériques peuvent retourner le type générique :
public static <T> T getFirst(T[] array) {
if (array.length > 0) {
return array[0];
}
return null;
}Plusieurs paramètres de type peuvent être utilisés :
public static <K, V> void printPair(K key, V value) {
System.out.println(key + ": " + value);
}
printPair("Age", 25); // String et Integer
printPair(1, "First"); // Integer et StringLes méthodes génériques sont utiles dans les classes utilitaires pour des opérations flexibles et réutilisables sans créer de classe générique.
Essayez vous-même
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lire les entrées
String firstWord = scanner.nextLine();
String secondWord = scanner.nextLine();
int firstNumber = scanner.nextInt();
int secondNumber = scanner.nextInt();
// TODO: Créer un tableau String[] contenant les deux mots
// TODO: Utiliser ArrayUtils.getLast pour obtenir le dernier élément
// Afficher : "Last word: [result]"
// TODO: Créer un tableau Integer[] contenant les deux nombres
// TODO: Appeler ArrayUtils.swap pour échanger les éléments aux indices 0 et 1
// Afficher : "After swap: [first], [second]"
// TODO: Appeler ArrayUtils.printWithLabel avec firstWord comme étiquette et firstNumber comme valeur
// TODO: Appeler ArrayUtils.printWithLabel avec firstNumber comme étiquette et secondWord comme valeur
}
}
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
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesChamps (Attributs)Méthode constructeurSurcharge de constructeurRécapitulatif - Calculatrice simple4Héritage
Héritage de base (extends)Le mot-clé superRedéfinition de méthode (@Override)Chaînage de constructeursLa classe ObjectHéritage simple et multiniveauPourquoi pas d'héritage multiple de classesRécapitulatif - Hiérarchie des employés7Méthodes spéciales et classe Object
Méthode toString()equals() et hashCode()Méthode clone()compareTo() et ComparableInterface ComparatorRécapitulatif - Tri personnalisé2Modificateurs d'accès et Encapsulation
Aperçu des niveaux d'accèsMéthodes Getter et SetterMasquage d'informationsLe mot-clé finalRécapitulatif - Gestionnaire de compte bancaire5Polymorphisme
Bases de la surcharge de méthodesRedéfinition de méthodes (Run-Time)Upcasting et DowncastingL'opérateur instanceofClasses et méthodes abstraitesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageAgrégation vs CompositionClasses internes, imbriquées et anonymesEnums et méthodes d'EnumRecords (Java 16+)Classes scellées (Java 17+)11Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron MonteurPatron ObservateurPatron Stratégie3Propriétés de classe et membres statiques
Variables d'instance vs variables statiquesMéthodes statiquesBlocs statiquesConstantes (static final)Récapitulatif - Compteur et utilitaire6Interfaces et Classes Abstraites
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesDefault et Static dans les InterfacesClasses Abstraites vs InterfacesInterfaces FonctionnellesRécapitulatif - Système de Paiement9La généricité
Introduction à la généricitéClasses génériquesMéthodes génériquesParamètres de type bornésWildcards (?, extends, super)Récapitulatif - Conteneur générique12Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositePatron Itérateur