Generics in Java: wozu sie dienen und wie man sie verwendet
Generics (Generics) sind eine der wichtigsten Funktionen von Java, die in der Version J2SE 5.0 eingeführt wurden. Sie ermöglichen die Erstellung von Klassen, Schnittstellen und Methoden, die mit Datentypen arbeiten, die zum Zeitpunkt des Aufrufs angegeben werden. Anstatt separate Implementierungen für Integer, String und Double zu schreiben, schreiben Sie einen einzigen universellen Code. In diesem Artikel werden wir untersuchen, wozu Generics in Java dienen, wie man sie in der Praxis verwendet und welche Fallstricke man kennen sollte.
Wozu dienen Generics in Java?
Vor der Einführung von Generics verwendeten Entwickler Object, um beliebige Typen zu speichern. Das funktionierte, führte aber zu zwei ernsthaften Problemen:
- Fehlende Typprüfung zur Kompilierzeit. Sie konnten versehentlich einen
Stringanstelle einesIntegerin eine Liste einfügen, und der Fehler zeigte sich erst zur Laufzeit des Programms. - Notwendigkeit expliziter Typumwandlungen. Jedes Mal beim Abrufen eines Elements aus einer Sammlung war eine Umwandlung erforderlich:
(String) list.get(0). Das machte den Code umständlich und fehleranfällig.
Generics lösen beide Probleme. Sie ermöglichen es dem Compiler, die Korrektheit der Typen zu überprüfen und die Umwandlung automatisch durchzuführen. Betrachten wir ein einfaches Beispiel:
// Ohne Generics (alter Stil)List list = new ArrayList();list.add("Hello");String s = (String) list.get(0); // explizite Umwandlung nötig
// Mit GenericsList<String> list = new ArrayList<>();list.add("Hello");String s = list.get(0); // keine Umwandlung erforderlichDer Code ist sicherer und lesbarer geworden. Ein Typfehler wird zur Kompilierzeit erkannt, nicht zur Laufzeit.
Wie man Generics verwendet: grundlegende Konstrukte
1. Generic-Klassen
Sie können eine Klasse definieren, die einen oder mehrere Typparameter akzeptiert. Am häufigsten wird ein einzelner Buchstabe verwendet: T (Type), E (Element), K (Key), V (Value).
public class Box<T> { private T content;
public void put(T item) { this.content = item; }
public T get() { return content; }}
// VerwendungBox<String> stringBox = new Box<>();stringBox.put("Java");String value = stringBox.get(); // automatische UmwandlungDer Parameter T wird bei der Objekterstellung durch den tatsächlichen Typ ersetzt. Der Compiler garantiert, dass in eine Box<String> kein Integer eingefügt werden kann.
2. Generic-Methoden
Methoden können ebenfalls generisch sein, selbst wenn die Klasse nicht generisch ist. Der Typparameter wird vor dem Rückgabetyp angegeben:
public class Utils { public static <T> T getMiddle(T... args) { return args[args.length / 2]; }}
// AufrufString middle = Utils.<String>getMiddle("A", "B", "C");// oder einfach: Utils.getMiddle("A", "B", "C") — der Compiler leitet den Typ abGeneric-Methoden sind nützlich für Hilfsfunktionen, die mit verschiedenen Datentypen arbeiten.
3. Eingeschränkte Typen (Bounded Type Parameters)
Manchmal muss man einschränken, welche Typen eingesetzt werden können. Zum Beispiel, damit eine Methode nur mit Zahlen arbeitet:
public class Calculator { public static <T extends Number> double sum(T a, T b) { return a.doubleValue() + b.doubleValue(); }}
// Funktioniert mit Integer, Double, Float usw.double result = Calculator.sum(5, 10); // 15.0Das Schlüsselwort extends bedeutet, dass T ein Untertyp der angegebenen Klasse sein muss (oder eine Schnittstelle implementieren muss).
Wildcards: unbekannte Typen
Wildcards (Platzhalter) werden verwendet, wenn der genaue Typ unbekannt oder unwichtig ist. Sie werden durch das Fragezeichen ? gekennzeichnet. Es gibt drei Arten:
Blogs
Buchempfehlungen
Lesen Sie auch
Reflexion in Java: Was ist das und wozu braucht man sie? Vollständiges Tutorial mit Beispielen
C# im Jahr 2025: Neue Möglichkeiten in der Praxis
Gehälter von TypeScript-Entwicklern in Russland: Marktüberblick 2025
Dependency Injection in C++ in der Praxis: Beispiele und Vorlagen
Server-Sent Events in Go: Reaktive Webanwendungen ohne WebSocket