Java Reference
In-Depth Information
Es ist aber nicht möglich, eine konkrete Klasse als Typparameter anzugeben, die außerhalb
des Vererbungsbaums liegt, der MyClass1 als Wurzel hat. Die folgende Anweisung ist zum
Beispiel syntaktisch falsch („Bound mismatch: The type String is not a valid substitute . . .“):
GenericClass<String> d = new GenericClass<String>();
Wenn wir also bisher eine Klasse C<T> defi niert haben, dann war das eine vereinfachende
Schreibweise für C<T extends Object>.
Es ist auch möglich, mehrfache Einschränkungen anzugeben:
class A {...}
interface I1 {...}
interface I2 {...}
class GenericClass<T extends A & I1 & I2> {...}
Die zuerst angegebene Einschränkung (im obigen Beispiel A) kann eine Klasse oder eine
Schnittstelle sein. Alle weiteren Einschränkungen (nach &) müssen Schnittstellen sein.
1 .5 Umsetzung des Generics-Konzepts
Um einige Einschränkungen der Generics in Java zu verstehen, ist es hilfreich zu wissen,
wie dieses Sprachkonzept realisiert wird. Generics gehörten nicht von Anfang an zum
Sprachumfang von Java, sondern wurden erst in Version 5 eingeführt. Ein Ziel dabei war,
dass die JVM (Java Virtual Machine), welche den vom Java-Compiler generierten Byte-Code
interpretiert, dafür nicht geändert werden sollte. Mit anderen Worten: Die JVM weiß nichts
von Generics und der Byte-Code enthält keine Angaben, wo im Quellcode Generics verwen-
det wurden. Man bezeichnet die Entfernung der Generics-Eigenscha en aus dem Byte-
Code als Typlöschung (Type Erasure). Bitte verwechseln Sie den Byte-Code nicht mit den
Informationen über Klassen, Methoden usw., die über Refl ection erfragt werden können;
über Refl ection kann man sehr wohl die Generics-Eigenscha en herausfi nden, wie im fol-
genden Kapitel zu sehen sein wird. Der Compiler prü zwar, ob die Syntax auch bzgl.
Generics korrekt ist (Beispiele für Warnungen und Syntaxfehler im Zusammenhang mit
Generics wurden zuvor schon präsentiert). Im erzeugten Byte-Code einer Klasse werden
aber alle Vorkommen eines parametrisieren Typs T durch Object (für eine Klasse C<T>)
bzw. durch A (für eine Klasse C<T extends A>) ersetzt. Zu einer parametrisierten Klasse
gibt es auch nur ein einziges Class-Objekt (s. Kapitel über Refl ection), und es wird dafür
auch nur einmal Byte-Code erzeugt (nicht für jedes Einsetzen einer konkreten Klasse als
Typparameter).
Wegen der oben beschriebenen Typlöschung (Type Erasure) kann man einem GenericStack-
Objekt nicht mehr ansehen, für welchen konkreten Typ es erzeugt wurde. Man kann zwar
überprüfen, ob ein GenericStack-Objekt beispielsweise nur String-Elemente enthält. Aber
man kann daraus nicht folgern, ob es als GenericStack<String> angelegt wurde und nur
Strings enthalten darf oder ob es als GenericStack<Object> angelegt wurde, momentan nur
zufällig Strings enthält und zukün ig auch mit Objekten jeder beliebigen anderen Klasse
 
Search WWH ::




Custom Search