Datentypen in Java: So funktionieren Generics

Ein nützliches Feature in C/C++ sind Parameterlisten variabler Länge. Vor der Version 1.5 gibt es solche in Java nicht. Diese Parameter werden als einfaches Array gespeichert. Die Aufrufe in der main-Methode sind alle für diese Methodendeklaration gültig. Hier ein Beispiel für die neue Syntax:


Mit Wildcards Grenzen setzen

Parameter generischen Typs sind in Java nicht auf bestimmte Klassen beschränkt. Java erlaubt die Verwendung von Wildcards, um den Typ der Parameter einzuschränken, den ein bestimmtes generisches Objekt verwenden darf. Wildcards sind Typ-Parameter der Form „?“, wobei zusätzlich noch eine Beschränkung angegeben werden kann. Da der exakte Typ eines Objekts mit einer Wildcard unbekannt ist, gibt es Einschränkungen hinsichtlich der Arten von Methoden, die für das Objekt aufgerufen werden können.

Hier ein Beispiel für eine unbeschränkte Wildcard: List<?> ist eine Liste, deren Objekttyp unbekannt ist. Methoden, die eine solche Liste als Parameter übernehmen, können jede Art von Liste verwenden, unabhängig vom Parametertyp. Das Auslesen der Liste ergibt Objekte vom Typ Object. Ein Hinzufügen von Werten ungleich null zur Liste ist nicht zulässig, da der Parametertyp nicht bekannt ist.

Das Schlüsselwort extends wird verwendet, um die obere Beschränkung eines generischen Elements anzugeben. Die Bezeichnung extends gibt zugleich an, dass der generische Typ ein Subtyp der beschränkenden Klasse ist. Daher muss sie die Klasse entweder erweitern oder das Interface der beschränkenden Klasse implementieren. List<? extends Number> bedeutet, dass die entsprechende Liste Objekte enthält, die die Klasse Number erweitern. Die Liste könnte zum Beispiel List<Float> oder List<Number> sein. Das Lesen eines Elements aus der Liste ergibt eine Number, während das Schreiben von Null-Werten in die Liste nicht zulässig ist.

Entspechend wird das Schlüsselwort super verwendet, um die untere Beschränkung eines generischen Elements anzugeben. Die Bezeichnung super identifiziert dabei den generischen Typ als Supertyp der beschränkenden Klasse. List<? super Number> kann etwa List<Number> oder List<Object> sein. Das Lesen aus der Liste liefert Objekte vom Typ Object. Jedes Element vom Typ Number kann der Liste hinzugefügt werden, da garantiert ist, dass es ein für die Liste gültiger Typ ist.

Fazit

Generics sind extrem raffiniert, aber auch kniffelig. Die meisten der etwas seltsamen Eigenschaften von Generics rühren daher, dass sie ausschließlich in Kompilierzeit funktionieren. Sie hinterlassen dank des Type-Erasure-Verfahrens fast keine Spuren im Laufzeitcode. Wenn man beispielsweise ArrayList dekompiliert, wo sich zahllose Generics im Quellcode tummeln, findet sich keine Spur von Generics in der Klassendatei. Diese speichert und liefert nur gewöhnliche Objekte, ohne jegliche Typumwandlung.

Das einzige Indiz für die Verwendung von Generics sind die Casts, die automatisch in die get-Methoden des Aufrufers eingefügt wurden, um die Objekte in den Typ der entsprechenden Variablen umzuwandeln. In ArrayList selbst findet sich kein Umwandlungscode. Daher kann der generische Code so einfache Aufgaben wie „ein Objekt vom Typ T erstellen“ oder „ein Objekt in Typ T umwandeln“ nicht erledigen.

Weitere Informationen zum Thema Generics:

Allgemeine Einführung (Sun Microsystems)

Generics in der Programmiersprache Java (Gilad Bracha)

Themenseiten: Anwendungsentwicklung, Software

Fanden Sie diesen Artikel nützlich?
Content Loading ...
Whitepaper

Artikel empfehlen:

Neueste Kommentare 

Noch keine Kommentare zu Datentypen in Java: So funktionieren Generics

Kommentar hinzufügen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *