Zum Inhalt springen

„Wildcard (Java)“ – Versionsunterschied

aus Wikipedia, der freien Enzyklopädie
[gesichtete Version][gesichtete Version]
Inhalt gelöscht Inhalt hinzugefügt
K fixed typo
tk k
Zeile 1: Zeile 1:
Die '''Wildcard''' (selten auch '''Joker''') <syntaxhighlight enclose="none" lang="java">?</syntaxhighlight> ist in [[Java (Programmiersprache)|Java]] ein spezieller aktueller Typparameter für die Instanziierung [[Generische Programmierung in Java|generischer (parametrisierter) Typen]].<ref>{{Internetquelle | url=http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.5.1 | titel=Chapter 4. Types, Values, and Variables | titelerg=4.5.1. Type Arguments and Wildcards | autor=James Gosling u.&nbsp;a. | werk=Java Language Specification | datum=2013-02-28 | zugriff=2013-01-14 | sprache=englisch }}</ref> In diesem Artikel werden die wichtigsten Regeln für seine Verwendung zusammengefasst.
Die '''Wildcard''' (selten auch '''Joker''') <syntaxhighlight lang="java" inline>?</syntaxhighlight> ist in [[Java (Programmiersprache)|Java]] ein spezieller aktueller Typparameter für die Instanziierung [[Generische Programmierung in Java|generischer (parametrisierter) Typen]].<ref>{{Internetquelle | url=http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.5.1 | titel=Chapter 4. Types, Values, and Variables | titelerg=4.5.1. Type Arguments and Wildcards | autor=James Gosling u.&nbsp;a. | werk=Java Language Specification | datum=2013-02-28 | zugriff=2013-01-14 | sprache=en}}</ref> In diesem Artikel werden die wichtigsten Regeln für seine Verwendung zusammengefasst.


== Kovarianz für generische Typen ==
== Kovarianz für generische Typen ==
Im Gegensatz zu [[Feld (Datentyp)|Arrays]] (die in Java [[Kovarianz und Kontravarianz|kovariant]] sind) sind unterschiedliche Instanziierungen eines generischen Typs untereinander nicht (auch nicht explizit) kompatibel: Nach den Vereinbarungen <syntaxhighlight enclose="none" lang="java">Generisch<Obertyp> oberGenerisch; Generisch<Untertyp> unterGenerisch;</syntaxhighlight> meldet der Compiler bei beiden [[Typumwandlung|Konvertierungen]] (castings) <syntaxhighlight enclose="none" lang="java">(Generisch<Untertyp>)oberGenerisch</syntaxhighlight> und <syntaxhighlight enclose="none" lang="java">(Generisch<Obertyp>)unterGenerisch</syntaxhighlight> einen Fehler.
Im Gegensatz zu [[Feld (Datentyp)|Arrays]] (die in Java [[Kovarianz und Kontravarianz|kovariant]] sind) sind unterschiedliche Instanziierungen eines generischen Typs untereinander nicht (auch nicht explizit) kompatibel: Nach den Vereinbarungen <syntaxhighlight lang="java" inline>Generisch<Obertyp> oberGenerisch; Generisch<Untertyp> unterGenerisch;</syntaxhighlight> meldet der Compiler bei beiden [[Typumwandlung|Konvertierungen]] (castings) <syntaxhighlight lang="java" inline>(Generisch<Untertyp>)oberGenerisch</syntaxhighlight> und <syntaxhighlight lang="java" inline>(Generisch<Obertyp>)unterGenerisch</syntaxhighlight> einen Fehler.


Diese Inkompatibilität kann mit der Wildcard aufgeweicht werden, wenn <syntaxhighlight enclose="none" lang="java">?</syntaxhighlight> für einen aktuellen Typparameter eingesetzt wird: <syntaxhighlight enclose="none" lang="java">Generisch<?></syntaxhighlight> ist der abstrakter Obertyp aller Instanziierungen des generischen Typs. Das heißt, von diesem Typ können nur Referenzen, keine Objekte gebildet werden. Der Sinn einer solchen Referenz ist, dass zu ihr beliebige Instanziierungen von <syntaxhighlight enclose="none" lang="java">Generisch</syntaxhighlight> passen.
Diese Inkompatibilität kann mit der Wildcard aufgeweicht werden, wenn <syntaxhighlight lang="java" inline>?</syntaxhighlight> für einen aktuellen Typparameter eingesetzt wird: <syntaxhighlight lang="java" inline>Generisch<?></syntaxhighlight> ist der abstrakter Obertyp aller Instanziierungen des generischen Typs. Das heißt, von diesem Typ können nur Referenzen, keine Objekte gebildet werden. Der Sinn einer solchen Referenz ist, dass zu ihr beliebige Instanziierungen von <syntaxhighlight lang="java" inline>Generisch</syntaxhighlight> passen.


== Wildcard als Parametertyp ==
== Wildcard als Parametertyp ==
Im Rumpf der generischen Einheit wird der Typparameter wie die obere Schranke (wenn uneingeschränkt, dann wie <syntaxhighlight enclose="none" lang="java">Object</syntaxhighlight>) gehandhabt. Wenn der Ergebnistyp (return type) einer Funktion der Typparameter ist, kann das Ergebnis (z.B. vom Typ <syntaxhighlight enclose="none" lang="java">?</syntaxhighlight>) in eine Referenz vom Typ der Schranke (<syntaxhighlight enclose="none" lang="java">Object</syntaxhighlight>, wenn keine Schranke) übernommen werden. In die andere Richtung, zum Wildcard-Typ passt kein anderer Typ, nicht einmal <syntaxhighlight enclose="none" lang="java">Object</syntaxhighlight>: Wenn <syntaxhighlight enclose="none" lang="java">?</syntaxhighlight> für den Typ des formalen Parameters einer Methode eingesetzt wurde, können ihr keine aktuellen Parameter übergeben werden. Sie kann dann nur nach Konvertierung (casting) der Wildcard-Referenz aufgerufen werden:
Im Rumpf der generischen Einheit wird der Typparameter wie die obere Schranke (wenn uneingeschränkt, dann wie <syntaxhighlight lang="java" inline>Object</syntaxhighlight>) gehandhabt. Wenn der Ergebnistyp (return type) einer Funktion der Typparameter ist, kann das Ergebnis (z.&nbsp;B. vom Typ <syntaxhighlight lang="java" inline>?</syntaxhighlight>) in eine Referenz vom Typ der Schranke (<syntaxhighlight lang="java" inline>Object</syntaxhighlight>, wenn keine Schranke) übernommen werden. In die andere Richtung, zum Wildcard-Typ passt kein anderer Typ, nicht einmal <syntaxhighlight lang="java" inline>Object</syntaxhighlight>: Wenn <syntaxhighlight lang="java" inline>?</syntaxhighlight> für den Typ des formalen Parameters einer Methode eingesetzt wurde, können ihr keine aktuellen Parameter übergeben werden. Sie kann dann nur nach Konvertierung (casting) der Wildcard-Referenz aufgerufen werden:


<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
Zeile 29: Zeile 29:
</syntaxhighlight>
</syntaxhighlight>


In diese Referenz kann nun eine Instanz von <syntaxhighlight enclose="none" lang="java">Generisch</syntaxhighlight> eingehängt werden, wo der aktuelle
In diese Referenz kann nun eine Instanz von <syntaxhighlight lang="java" inline>Generisch</syntaxhighlight> eingehängt werden, wo der aktuelle
Typparameter ein Untertyp von <syntaxhighlight enclose="none" lang="java">UntertypVonSchranke</syntaxhighlight> ist. In eine Einschränkung von unten
Typparameter ein Untertyp von <syntaxhighlight lang="java" inline>UntertypVonSchranke</syntaxhighlight> ist. In eine Einschränkung von unten


<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
Zeile 36: Zeile 36:
</syntaxhighlight>
</syntaxhighlight>


können Instanziierungen von <syntaxhighlight enclose="none" lang="java">Generisch</syntaxhighlight> mit einem beliebigen Obertyp (z.&nbsp;B. <syntaxhighlight enclose="none" lang="java">Schranke</syntaxhighlight>) von <syntaxhighlight enclose="none" lang="java">UntertypVonSchranke</syntaxhighlight> eingehängt werden. Es ist also möglich, dass die zugelassenen Typen von zwei Seiten eingeschränkt werden: von oben durch die Klassenvereinbarung (<syntaxhighlight enclose="none" lang="java">extends Schranke</syntaxhighlight>), von unten durch die Referenzvereinbarung (<syntaxhighlight enclose="none" lang="java">super UntertypVonSchranke</syntaxhighlight>).
können Instanziierungen von <syntaxhighlight lang="java" inline>Generisch</syntaxhighlight> mit einem beliebigen Obertyp (z.&nbsp;B. <syntaxhighlight lang="java" inline>Schranke</syntaxhighlight>) von <syntaxhighlight lang="java" inline>UntertypVonSchranke</syntaxhighlight> eingehängt werden. Es ist also möglich, dass die zugelassenen Typen von zwei Seiten eingeschränkt werden: von oben durch die Klassenvereinbarung (<syntaxhighlight lang="java" inline>extends Schranke</syntaxhighlight>), von unten durch die Referenzvereinbarung (<syntaxhighlight lang="java" inline>super UntertypVonSchranke</syntaxhighlight>).


== Objekterzeugung mit Wildcard-Instanziierungen ==
== Objekterzeugung mit Wildcard-Instanziierungen ==
Obwohl von Wildcard-Instanziierungen keine Objekte erzeugt werden können (<syntaxhighlight enclose="none" lang="java">new Generisch<?>()</syntaxhighlight> ist also verboten, weil <syntaxhighlight enclose="none" lang="java">Generisch<?></syntaxhighlight> abstrakt ist), können Array-Objekte nur von uneingeschränkten Wildcard-Instanziierungen (also von keinen anderen generischen Instanziierungen) erzeugt werden: <syntaxhighlight enclose="none" lang="java">new Generisch<?>[20]</syntaxhighlight> ist korrekt, während <syntaxhighlight enclose="none" lang="java">new Generisch<Schranke>[20]</syntaxhighlight> verboten ist.
Obwohl von Wildcard-Instanziierungen keine Objekte erzeugt werden können (<syntaxhighlight lang="java" inline>new Generisch<?>()</syntaxhighlight> ist also verboten, weil <syntaxhighlight lang="java" inline>Generisch<?></syntaxhighlight> abstrakt ist), können Array-Objekte nur von uneingeschränkten Wildcard-Instanziierungen (also von keinen anderen generischen Instanziierungen) erzeugt werden: <syntaxhighlight lang="java" inline>new Generisch<?>[20]</syntaxhighlight> ist korrekt, während <syntaxhighlight lang="java" inline>new Generisch<Schranke>[20]</syntaxhighlight> verboten ist.

== Einzelnachweise ==
<references/>


== Literatur ==
== Literatur ==
* The Java Language Specification, Third Edition (Sun), ISBN 978-0-321-24678-3
* ''The Java Language Specification'', Third Edition. Sun, ISBN 978-0-321-24678-3

* Java Tutorials, Lesson Generics http://download.oracle.com/javase/tutorial/java/generics/index.html
== Weblinks ==
* Typkompatibilität in Java http://public.beuth-hochschule.de/~solymosi/veroeff/typkompatibilitaet/Typkompatibilitaet.html#Joker
* [http://download.oracle.com/javase/tutorial/java/generics/index.html ''Generics''.] Java Tutorials
* [http://public.beuth-hochschule.de/~solymosi/veroeff/typkompatibilitaet/Typkompatibilitaet.html#Joker Typkompatibilität in Java]

== Einzelnachweise ==
<references />


[[Kategorie:Java (Programmiersprache)]]
[[Kategorie:Java (Programmiersprache)]]

Version vom 16. Juli 2015, 23:45 Uhr

Die Wildcard (selten auch Joker) ? ist in Java ein spezieller aktueller Typparameter für die Instanziierung generischer (parametrisierter) Typen.[1] In diesem Artikel werden die wichtigsten Regeln für seine Verwendung zusammengefasst.

Kovarianz für generische Typen

Im Gegensatz zu Arrays (die in Java kovariant sind) sind unterschiedliche Instanziierungen eines generischen Typs untereinander nicht (auch nicht explizit) kompatibel: Nach den Vereinbarungen Generisch<Obertyp> oberGenerisch; Generisch<Untertyp> unterGenerisch; meldet der Compiler bei beiden Konvertierungen (castings) (Generisch<Untertyp>)oberGenerisch und (Generisch<Obertyp>)unterGenerisch einen Fehler.

Diese Inkompatibilität kann mit der Wildcard aufgeweicht werden, wenn ? für einen aktuellen Typparameter eingesetzt wird: Generisch<?> ist der abstrakter Obertyp aller Instanziierungen des generischen Typs. Das heißt, von diesem Typ können nur Referenzen, keine Objekte gebildet werden. Der Sinn einer solchen Referenz ist, dass zu ihr beliebige Instanziierungen von Generisch passen.

Wildcard als Parametertyp

Im Rumpf der generischen Einheit wird der Typparameter wie die obere Schranke (wenn uneingeschränkt, dann wie Object) gehandhabt. Wenn der Ergebnistyp (return type) einer Funktion der Typparameter ist, kann das Ergebnis (z. B. vom Typ ?) in eine Referenz vom Typ der Schranke (Object, wenn keine Schranke) übernommen werden. In die andere Richtung, zum Wildcard-Typ passt kein anderer Typ, nicht einmal Object: Wenn ? für den Typ des formalen Parameters einer Methode eingesetzt wurde, können ihr keine aktuellen Parameter übergeben werden. Sie kann dann nur nach Konvertierung (casting) der Wildcard-Referenz aufgerufen werden:

class Generisch<T extends Schranke> {
    private T t;
    void schreiben(T t) { this.t = t; }
    T lesen() { return t; }
}
...
Generisch<?> jokerReferenz;
Schranke o = jokerReferenz.lesen(); // Object wäre auch OK
jokerReferenz.schreiben(new Object()); // Typfehler
((Generisch<Schranke>)jokerReferenz).schreiben(new Schranke()); // OK

Einschränkung der Wildcard

Nicht nur der formale Typparameter, auch die Wildcard kann (weiter) von oben eingeschränkt werden, wenn man nicht beliebige Instanziierungen kompatibel halten möchte:

Generisch<? extends UntertypVonSchranke> vonObenEingeschränkteReferenz;

In diese Referenz kann nun eine Instanz von Generisch eingehängt werden, wo der aktuelle Typparameter ein Untertyp von UntertypVonSchranke ist. In eine Einschränkung von unten

Generisch<? super UntertypVonSchranke> vonUntenEingeschränkteReferenz;

können Instanziierungen von Generisch mit einem beliebigen Obertyp (z. B. Schranke) von UntertypVonSchranke eingehängt werden. Es ist also möglich, dass die zugelassenen Typen von zwei Seiten eingeschränkt werden: von oben durch die Klassenvereinbarung (extends Schranke), von unten durch die Referenzvereinbarung (super UntertypVonSchranke).

Objekterzeugung mit Wildcard-Instanziierungen

Obwohl von Wildcard-Instanziierungen keine Objekte erzeugt werden können (new Generisch<?>() ist also verboten, weil Generisch<?> abstrakt ist), können Array-Objekte nur von uneingeschränkten Wildcard-Instanziierungen (also von keinen anderen generischen Instanziierungen) erzeugt werden: new Generisch<?>[20] ist korrekt, während new Generisch<Schranke>[20] verboten ist.

Literatur

Einzelnachweise

  1. James Gosling u. a.: Chapter 4. Types, Values, and Variables. 4.5.1. Type Arguments and Wildcards. In: Java Language Specification. 28. Februar 2013, abgerufen am 14. Januar 2013 (englisch).