Generische Klassen
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 54 von 87.
Nachdem Sie nun verstehen, warum Generics nützlich sind, lassen Sie uns Ihre eigene generische Klasse erstellen. Eine generische Klasse deklariert einen oder mehrere Typparameter in spitzen Klammern nach dem Klassennamen, die dann in der gesamten Klasse verwendet werden können.
class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}Das T ist ein Typparameter – ein Platzhalter, der durch einen tatsächlichen Typ ersetzt wird, wenn Sie eine Instanz erstellen. Sie können jeden beliebigen Namen verwenden, aber einzelne Großbuchstaben sind üblich: T für Type, E für Element, K für Key, V für Value.
Beim Instanziieren einer generischen Klasse geben Sie den tatsächlichen Typ in spitzen Klammern an:
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get(); // Kein Casting erforderlich
Box<Integer> intBox = new Box<>();
intBox.set(42);
Integer num = intBox.get();Beachten Sie den <> (Diamond-Operator) auf der rechten Seite – Java leitet den Typ aus der Deklaration ab. Sie können auch mehrere Typparameter für Klassen verwenden, die mit mehr als einem Typ arbeiten müssen:
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
Pair<String, Integer> pair = new Pair<>("age", 25);Aufgabe
EinfachLassen Sie uns ein Geschenkregistersystem bauen, das die Leistungsfähigkeit generischer Klassen demonstriert. Sie erstellen ein flexibles Aufbewahrungssystem, das jede Art von Geschenkartikel aufnehmen kann, sowie ein Register, das Geschenk Namen mit ihren Details unter Verwendung mehrerer Typparameter verknüpft.
Sie werden Ihren Code über drei Dateien organisieren:
GiftBox.java: Erstellen Sie eine generische Klasse, die jede Art von Geschenk verpacken kann. IhreGiftBox<T>sollte ein privates Felditemvom TypTund ein privates Feldwrapped(boolean) haben, das alsfalsebeginnt. Fügen Sie einen Konstruktor hinzu, der das Element akzeptiert, einegetItem()-Methode, die das Element zurückgibt, einewrap()-Methode, die wrapped auf true setzt, und eineisWrapped()-Methode, die den Verpackungsstatus zurückgibt. Fügen Sie einegetStatus()-Methode hinzu, die entweder[item] (wrapped)oder[item] (unwrapped)zurückgibt, abhängig vom Verpackungszustand.Registry.java: Erstellen Sie eine generische Klasse mit zwei Typparametern, die einen Empfänger mit seinem Geschenk verknüpft. IhreRegistry<K, V>sollte private Felderrecipientvom TypKundgiftvom TypVhaben. Fügen Sie einen Konstruktor hinzu, der beide Werte akzeptiert, Getter-MethodengetRecipient()undgetGift()sowie einegetEntry()-Methode, die Folgendes zurückgibt:[recipient] -> [gift]Main.java: Erwecken Sie Ihr Geschenkregister zum Leben! Sie erhalten drei Eingaben: einen Empfängernamen (String), eine Geschenkbezeichnung (String) und einen Geschenkwert (Ganzzahl, die Dollar darstellt).Erstellen Sie zuerst eine
GiftBox<String>, die die Geschenkbezeichnung enthält. Verpacken Sie diese mit derwrap()-Methode und geben Sie dann ihren Status aus.Erstellen Sie als Nächstes eine
GiftBox<Integer>, die den Geschenkwert enthält (der einen Geschenkkartenbetrag darstellt). Verpacken Sie diese nicht – geben Sie ihren Status aus, um zu zeigen, dass sie unverpackt ist.Erstellen Sie schließlich eine
Registry<String, String>, die den Empfängernamen mit der Geschenkbezeichnung verknüpft, und geben Sie den Registereintrag aus.
Sie erhalten drei Eingaben in der folgenden Reihenfolge: Empfängername, Geschenkbezeichnung und Geschenkwert (als Ganzzahl).
Beachten Sie, wie dieselbe GiftBox-Klasse nahtlos mit den Typen String und Integer funktioniert – das ist die Schönheit von Generics! Und die Registry-Klasse zeigt, wie mehrere Typparameter es Ihnen ermöglichen, flexible Paarungen zwischen zwei beliebigen Typen zu erstellen.
Spickzettel
Eine generische Klasse deklariert einen oder mehrere Typparameter in spitzen Klammern nach dem Klassennamen, die innerhalb der gesamten Klasse verwendet werden können:
class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}Das T ist ein Typparameter – ein Platzhalter, der beim Erstellen einer Instanz durch einen tatsächlichen Typ ersetzt wird. Gängige Konventionen verwenden einzelne Großbuchstaben: T für Type, E für Element, K für Key, V für Value.
Geben Sie bei der Instanziierung einer generischen Klasse den tatsächlichen Typ in spitzen Klammern an:
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get(); // No casting needed
Box<Integer> intBox = new Box<>();
intBox.set(42);
Integer num = intBox.get();Der <> (Diamond-Operator) ermöglicht es Java, den Typ aus der Deklaration abzuleiten.
Verwenden Sie mehrere Typparameter für Klassen, die mit mehr als einem Typ arbeiten:
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
Pair<String, Integer> pair = new Pair<>("age", 25);Probier es selbst
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Eingaben lesen
String recipientName = scanner.nextLine();
String giftDescription = scanner.nextLine();
int giftValue = scanner.nextInt();
// TODO: Erstelle eine GiftBox<String>, die die Geschenkbeschreibung enthält
// TODO: Verpacke sie mit der wrap()-Methode
// TODO: Gib ihren Status mit getStatus() aus
// TODO: Erstelle eine GiftBox<Integer>, die den Geschenkwert enthält
// TODO: Diese nicht verpacken - gib ihren Status aus (sollte als unverpackt angezeigt werden)
// TODO: Erstelle ein Registry<String, String>, das den Empfänger mit der Geschenkbeschreibung verknüpft
// TODO: Gib den Registereintrag mit getEntry() aus
}
}
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