Generische Methoden
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 55 von 87.
Während generische Klassen bewirken, dass ganze Klassen mit verschiedenen Typen funktionieren, muss manchmal nur eine einzelne Methode generisch sein. Eine generische Methode deklariert ihren eigenen Typparameter, unabhängig von jeglichen Generics auf Klassenebene.
Der Typparameter erscheint vor dem Rückgabetyp in der Methodensignatur:
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); // Funktioniert mit String[]
Utility.printArray(numbers); // Funktioniert mit Integer[]Beachten Sie das <T>, das zwischen den Modifikatoren und dem Rückgabetyp platziert ist. Dies deklariert T als Typparameter für diese spezifische Methode. Der Compiler leitet den tatsächlichen Typ aus den Argumenten ab, die Sie übergeben.
Generische Methoden können auch den generischen Typ zurückgeben:
public static <T> T getFirst(T[] array) {
if (array.length > 0) {
return array[0];
}
return null;
}
String first = getFirst(new String[]{"a", "b"}); // Gibt "a" zurückSie können bei Bedarf mehrere Typparameter verwenden:
public static <K, V> void printPair(K key, V value) {
System.out.println(key + ": " + value);
}
printPair("Age", 25); // String und Integer
printPair(1, "First"); // Integer und StringGenerische Methoden sind besonders nützlich in Utility-Klassen, in denen Sie flexible, wiederverwendbare Operationen benötigen, ohne eine generische Klasse zu erstellen.
Aufgabe
EinfachLassen Sie uns ein Utility-Toolkit erstellen, das die Flexibilität generischer Methoden demonstriert. Sie werden eine Klasse mit wiederverwendbaren Methoden erstellen, die mit jedem Typ funktionieren und zeigen, wie generische Methoden unabhängig von generischen Klassen existieren können.
Sie werden Ihren Code in zwei Dateien organisieren:
ArrayUtils.java: Erstellen Sie eine Utility-Klasse, die generische Methoden für die Arbeit mit Arrays enthält. Ihre Klasse sollte drei statische generische Methoden haben:getLast- Eine generische Methode, die ein Array vom TypTentgegennimmt und das letzte Element zurückgibt. Wenn das Array leer ist, geben Sienullzurück.swap- Eine generische Methode, die ein Array vom TypTund zwei Ganzzahl-Indizes entgegennimmt und dann die Elemente an diesen Positionen vertauscht. Diese Methode gibt nichts zurück.printWithLabel- Eine generische Methode mit zwei TypparameternKundV. Sie nimmt ein Label vom TypKund einen Wert vom TypVentgegen und gibt diese im Format[label]: [value]aus.Main.java: Setzen Sie Ihre generischen Methoden ein! Sie erhalten vier Eingaben: zwei Wörter (Strings) und zwei Zahlen (Integer).Erstellen Sie zuerst ein
String[]Array, das beide Wörter enthält. Verwenden SiegetLast, um das letzte Element zu erhalten, und geben Sie aus:Last word: [result]Erstellen Sie als Nächstes ein
Integer[]Array, das beide Zahlen enthält. Rufen Sieswapauf, um die Elemente an den Indizes 0 und 1 zu vertauschen, und geben Sie dann aus:After swap: [first], [second]Demonstrieren Sie schließlich die generische Methode mit zwei Parametern, indem Sie
printWithLabelzweimal aufrufen:- Einmal mit dem ersten Wort als Label und der ersten Zahl als Wert
- Einmal mit der ersten Zahl als Label und dem zweiten Wort als Wert
Sie erhalten vier Eingaben in der Reihenfolge: erstes Wort, zweites Wort, erste Zahl, zweite Zahl.
Beachten Sie, wie jede Methode ihre eigenen Typparameter mit <T> oder <K, V> vor dem Rückgabetyp deklariert. Der Compiler leitet die tatsächlichen Typen aus den von Ihnen übergebenen Argumenten ab – es ist nicht erforderlich, sie beim Aufruf der Methoden explizit anzugeben!
Spickzettel
Eine generische Methode deklariert ihren eigenen Typparameter, unabhängig von Generics auf Klassenebene. Der Typparameter erscheint vor dem Rückgabetyp in der Methodensignatur.
Grundlegende Syntax einer generischen Methode:
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}Das <T> wird zwischen den Modifikatoren und dem Rückgabetyp platziert. Der Compiler leitet den tatsächlichen Typ aus den übergebenen Argumenten ab.
Generische Methoden können den generischen Typ zurückgeben:
public static <T> T getFirst(T[] array) {
if (array.length > 0) {
return array[0];
}
return null;
}Es können mehrere Typparameter verwendet werden:
public static <K, V> void printPair(K key, V value) {
System.out.println(key + ": " + value);
}
printPair("Age", 25); // String and Integer
printPair(1, "First"); // Integer and StringGenerische Methoden sind nützlich in Utility-Klassen für flexible, wiederverwendbare Operationen, ohne eine generische Klasse erstellen zu müssen.
Probier es selbst
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Eingaben lesen
String firstWord = scanner.nextLine();
String secondWord = scanner.nextLine();
int firstNumber = scanner.nextInt();
int secondNumber = scanner.nextInt();
// TODO: Erstelle ein String[] Array, das beide Wörter enthält
// TODO: Verwende ArrayUtils.getLast, um das letzte Element zu erhalten
// Ausgabe: "Last word: [result]"
// TODO: Erstelle ein Integer[] Array, das beide Zahlen enthält
// TODO: Rufe ArrayUtils.swap auf, um die Elemente an den Indizes 0 und 1 zu vertauschen
// Ausgabe: "After swap: [first], [second]"
// TODO: Rufe ArrayUtils.printWithLabel mit firstWord als Label und firstNumber als Wert auf
// TODO: Rufe ArrayUtils.printWithLabel mit firstNumber als Label und secondWord als Wert auf
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas this-SchlüsselwortMethodenFelder (Attribute)Konstruktor-MethodeKonstruktor-ÜberladungRückblick – Einfacher Taschenrechner4Vererbung
Grundlagen der Vererbung (extends)Das super-SchlüsselwortMethoden überschreiben (@Override)Konstruktor-VerkettungDie Object-KlasseEinfache & mehrstufige VererbungWarum keine Mehrfachvererbung von KlassenZusammenfassung - Mitarbeiter-Hierarchie7Spezielle Methoden & Object-Klasse
toString()-Methodeequals() und hashCode()clone()-MethodecompareTo() und ComparableComparator-InterfaceZusammenfassung – Benutzerdefiniertes Sortieren2Zugriffsmodifikatoren & Kapselung
Überblick über ZugriffsebenenGetter- und Setter-MethodenInformation HidingDas final-SchlüsselwortRückblick – Bankkonto-Manager5Polymorphismus
Grundlagen der MethodenüberladungMethodenüberschreibung (Laufzeit)Upcasting und DowncastingDer instanceof-OperatorAbstrakte Klassen und MethodenZusammenfassung – Formenrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungAggregation vs. KompositionInnere, geschachtelte & anonyme KlassenEnums und Enum-MethodenRecords (Java 16+)Sealed Classes (Java 17+)11Design Patterns Teil 1
Einführung in Design PatternsSingleton-PatternFactory-PatternBuilder-PatternObserver-PatternStrategy-Pattern14Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung3Klasseneigenschaften & Statische Member
Instanz- vs. statische VariablenStatische MethodenStatische BlöckeKonstanten (static final)Zusammenfassung – Zähler & Utility6Interfaces & Abstrakte Klassen
Einführung in InterfacesInterfaces implementierenImplementierung mehrerer InterfacesDefault- & statische Methoden in InterfacesAbstrakte Klassen vs. InterfacesFunktionale InterfacesZusammenfassung - Zahlungssystem