diff options
| author | Sven Eisenhauer <sven@sven-eisenhauer.net> | 2023-11-10 15:11:48 +0100 |
|---|---|---|
| committer | Sven Eisenhauer <sven@sven-eisenhauer.net> | 2023-11-10 15:11:48 +0100 |
| commit | 33613a85afc4b1481367fbe92a17ee59c240250b (patch) | |
| tree | 670b842326116b376b505ec2263878912fca97e2 /Master/Reference Architectures and Patterns/hjp5/html/k100105.html | |
| download | Studium-master.tar.gz Studium-master.tar.bz2 | |
Diffstat (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100105.html')
| -rw-r--r-- | Master/Reference Architectures and Patterns/hjp5/html/k100105.html | 1099 |
1 files changed, 1099 insertions, 0 deletions
diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100105.html b/Master/Reference Architectures and Patterns/hjp5/html/k100105.html new file mode 100644 index 0000000..58109c6 --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100105.html @@ -0,0 +1,1099 @@ +<html>
+<head>
+<title>
+Handbuch der Java-Programmierung, 5. Auflage
+</title>
+</head>
+<body>
+<a name="startofbody"></a>
+<script language="JavaScript" src="hjp4lib.js">
+</script>
+<script language="JavaScript">
+installKbdHandler("97,#startofbody;101,#endofbody;116,cover.html;122,k100003.html;115,search.html;105,index.html;100,JDKDOCS;112,APIDOCS;104,k100097.html;106,k100104.html;107,k100106.html;108,k100107.html");
+</script>
+<table border=0 cellpadding=0 cellspacing=1 width="100%">
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
+<td align="right">Handbuch der Java-Programmierung, 5. Auflage
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100097.html"> << </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100104.html"> < </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100106.html"> > </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100107.html"> >> </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
+<td align="right">Kapitel 15 - Collections II
+</table>
+<hr>
+
+
+<!-- Section -->
+<a name="typisierteklassen"></a>
+<h2>15.8 Typisierte Klassen und generische Collections <a name="ixa101015"></a>
+<a name="ixa101016"></a> <a name="ixa101017"></a> </h2>
+<hr>
+<ul>
+<li><a href="k100105.html#typisierteklassen">15.8 Typisierte Klassen und generische Collections
+ </a>
+<ul>
+<li><a href="k100105.html#sectlevel3id015008001">15.8.1 Grundlagen</a>
+<li><a href="k100105.html#sectlevel3id015008002">15.8.2 Collections mit mehreren Typparametern</a>
+<li><a href="k100105.html#eigenetypisiertelistenklasse">15.8.3 Eine eigene typisierte Listenklasse</a>
+<li><a href="k100105.html#sectlevel3id015008004">15.8.4 Typkompatibilität</a>
+<ul>
+<li><a href="k100105.html#sectlevel4id015008004001">Ober- und Unterklassen in generischen Typen</a>
+<li><a href="k100105.html#sectlevel4id015008004002">Der Wildcard ?</a>
+<li><a href="k100105.html#sectlevel4id015008004003">Gebundene Wildcards</a>
+</ul>
+<li><a href="k100105.html#sectlevel3id015008005">15.8.5 Sonstiges</a>
+</ul>
+</ul>
+<hr>
+
+
+<!-- Section -->
+<a name="sectlevel3id015008001"></a>
+<h3>15.8.1 Grundlagen </h3>
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Dieser Abschnitt beschreibt eine Erweiterung, die seit der J2SE 5.0
+zur Verfügung steht und unter dem Namen »Generics«
+bekannt geworden ist. Es geht dabei vordergründig um die Möglichkeit,
+typsichere Collection-Klassen zu definieren. Also solche, in die nicht
+nur allgemein Objekte des Typs <a href="index_o.html#ixb100224"><font color=#000080><tt>Object</tt></font></a>
+gesteckt werden können, sondern die durch vorhergehende Typisierung
+sicherstellen, dass nur Objekte des korrekten Typs (etwa <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>
+oder <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>)
+eingefügt werden können. Diese, von vielen Java-Entwicklern
+seit langer Zeit geforderte, Spracherweiterung bringt zwei wichtige
+Vorteile:
+<ul>
+<li>Da die Einfügeoperationen typsicher sind, kann zum Zugriffszeitpunkt
+kein fehlerhaft typisiertes Objekt mehr in der Collection sein. Bereits
+der Compiler stellt sicher, dass nur Objekte eingefügt werden
+können, die zur Collection passen. Ausnahmen des Typs <a href="index_c.html#ixb100729"><font color=#000080><tt>ClassCastException</tt></font></a>,
+die beim späteren Auslesen von fehlerhaft typisierten Collection-Elementen
+auftreten würden (also erst zur Laufzeit des Programms), gehören
+der Vergangenheit an.
+<li>Da der Compiler den Typ der Collection kennt, kann die umständliche
+Typkonvertierung beim Auslesen der Collection-Elemente entfallen,
+und der Programmcode wird kürzer und lesbarer.
+</ul>
+</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#FF9900">
+<tr>
+<td><font color="#FFFFFF"> JDK1.1-6.0 </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Genau genommen geht es nicht nur um Collections im eigentlichen Sinne,
+sondern um die Typisierung von beliebigen Java-Klassen. Also die Möglichkeit,
+festzulegen, dass eine bestimmte Klasse <font color="#000077"><tt>X</tt></font>
+zwar so <i>implementiert</i> wurde, dass sie prinzipiell mit allen
+anderen Klassen zusammen arbeitet (bzw. Objekte deren Typs aufnimmt),
+im konkreten Anwendungsfall von <font color="#000077"><tt>X</tt></font>
+aber die Möglichkeit besteht, die Zusammenarbeit (etwa aus Sicherheits-
+oder Konsistenzgründen) auf eine fest vorgegebene andere Klasse
+zu beschränken.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
+<tr>
+<td><font color="#FFFFFF"> Hinweis </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+<p>
+Was sich etwas kompliziert anhört, wollen wir durch ein einfaches
+Beispiel illustrieren:
+<a name="listingid015008"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> printSorted1(<font color="#006699">int</font>... args)
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> Vector v = <font color="#0000AA">new</font> Vector();
+<font color="#555555">004 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < args.length; ++i) {
+<font color="#555555">005 </font> v.addElement(<font color="#0000AA">new</font> Integer(args[i]));
+<font color="#555555">006 </font> }
+<font color="#555555">007 </font> Collections.sort(v);
+<font color="#555555">008 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < v.size(); ++i) {
+<font color="#555555">009 </font> <font color="#006699">int</font> wert = 10 * ((Integer)v.elementAt(i)).intValue();
+<font color="#555555">010 </font> System.out.print(wert + <font color="#0000FF">" "</font>);
+<font color="#555555">011 </font> }
+<font color="#555555">012 </font> System.out.println();
+<font color="#555555">013 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 15.8: Eine untypisierte Sortiermethode</i></p>
+
+<p>
+<font color="#000077"><tt>printSorted1</tt></font> bekommt als Parameter
+eine Menge von Ganzzahlen übergeben und hat die Aufgabe, diese
+mit 10 zu multiplizieren und sortiert auf der Konsole auszugeben.
+Die Methode legt dazu einen Vector <font color="#000077"><tt>v</tt></font>
+an und fügt in diesen zunächst die in <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>
+konvertierten <a href="index_i.html#ixb100244"><font color=#000080><tt>int</tt></font></a>-Werte
+ein. Anschließend sortiert sie den Vector, liest die <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>-Objekte
+aus, konvertiert sie in <a href="index_i.html#ixb100244"><font color=#000080><tt>int</tt></font></a>-Werte
+zurück und gibt die mit 10 multiplizierten Ergebnisse auf der
+Konsole aus.
+
+<p>
+Seit der J2SE 5.0 kann die Methode nun typsicher gemacht werden:
+<a name="listingid015009"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> printSorted2(<font color="#006699">int</font>... args)
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> Vector<Integer> v = <font color="#0000AA">new</font> Vector<Integer>();
+<font color="#555555">004 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < args.length; ++i) {
+<font color="#555555">005 </font> v.addElement(<font color="#0000AA">new</font> Integer(args[i]));
+<font color="#555555">006 </font> }
+<font color="#555555">007 </font> Collections.sort(v);
+<font color="#555555">008 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < v.size(); ++i) {
+<font color="#555555">009 </font> <font color="#006699">int</font> wert = 10 * v.elementAt(i).intValue();
+<font color="#555555">010 </font> System.out.print(wert + <font color="#0000FF">" "</font>);
+<font color="#555555">011 </font> }
+<font color="#555555">012 </font> System.out.println();
+<font color="#555555">013 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 15.9: Die typsichere Version der Sortiermethode</i></p>
+
+<p>
+Der <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+wurde hier mit einem Typ-Parameter versehen, der in spitzen Klammern
+angegeben wird:
+<font color="#000077">
+<pre>
+Vector<Integer> v = new Vector<Integer>();
+</pre>
+</font>
+
+<p>
+Dadurch wird dem Compiler mitgeteilt, dass dieser <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+ausschließlich <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>-Objekte
+aufnehmen kann. Alle Versuche, darin einen <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>,
+ein <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>
+oder irgendein anderes Nicht-Integer-Objekt zu speichern, werden vom
+Compiler unterbunden. Auch der zweite der oben genannten Vorteile
+kommt zum Tragen: beim Zugriff auf <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>-Elemente
+mit Hilfe der Methode <a href="index_e.html#ixb100683"><font color=#000080><tt>elementAt</tt></font></a>
+werden diese automatisch in ein <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>
+konvertiert, der übliche Typecast kann also entfallen.
+
+<p>
+Auf diese Weise können nun seit der J2SE 5.0 alle Collection-Klassen
+typsicher verwendet werden: einfach den Datentyp in spitzen Klammern
+direkt hinter dem Klassennamen angeben! Auch bei Collections, die
+mit mehr als einem Parameter arbeiten, ist das möglich, also
+inbesondere bei den verschiedenen Maps. Hier werden beide Parameter
+in spitzen Klammern angegeben und durch Kommata voneinander getrennt.
+Wir werden dazu später ein Beispiel sehen.
+
+<p>
+Zunächst soll jedoch das obige Beispiel weiter vereinfacht werden.
+Tatsächlich ist <font color="#000077"><tt>printSorted2</tt></font>
+nämlich etwas länger als <font color="#000077"><tt>printSorted1</tt></font>,
+d.h. wir haben uns die Typsicherheit durch <i>zusätzlichen</i>
+Code erkauft. Daß es wesentlich einfacher geht, zeigt folgende
+Variante:
+<a name="einfachtypsicher"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> printSorted3(<font color="#006699">int</font>... args)
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> Vector<Integer> v = <font color="#0000AA">new</font> Vector<Integer>();
+<font color="#555555">004 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i : args) {
+<font color="#555555">005 </font> v.addElement(i); <a name="einfachtypsicher.a"></a>
+<font color="#555555">006 </font> }
+<font color="#555555">007 </font> Collections.sort(v);
+<font color="#555555">008 </font> <font color="#0000AA">for</font> (Integer i : v) {
+<font color="#555555">009 </font> System.out.print((i * 10) + <font color="#0000FF">" "</font>); <a name="einfachtypsicher.b"></a>
+<font color="#555555">010 </font> }
+<font color="#555555">011 </font> System.out.println();
+<font color="#555555">012 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 15.10: Die vereinfachte Version der typsicheren Variante</i></p>
+
+<p>
+Hier kommen zusätzlich folgende Techniken zum Einsatz:
+<ul>
+<li>Dank Autoboxing wird der <a href="index_i.html#ixb100244"><font color=#000080><tt>int</tt></font></a>
+in <a href="k100105.html#einfachtypsicher.a">Zeile 005</a> automatisch
+in einen <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>
+konvertiert.
+<li>Dank Autounboxing funktioniert in <a href="k100105.html#einfachtypsicher.b">Zeile 009</a>
+auch die umgekehrte Richtung automatisch.
+<li>Dank der erweiterten <a href="index_f.html#ixb100078"><font color=#000080><tt>for</tt></font></a>-Schleife
+kann sowohl die Einfüge- als auch die Ausgabeschleife erheblich
+verkürzt werden.
+</ul>
+
+<p>
+Dieses Programm sieht wesentlich besser aus als die erste Fassung.
+Es ist nun sowohl typsicher als auch besser lesbar. Möglich gemacht
+wird dies durch verschiedene Neuerungen der J2SE 5.0, die hier im
+Zusammenspiel ihr Synergiepotential entfalten. Autoboxing und Autounboxing
+werden in <a href="k100066.html#autoboxing">Abschnitt 10.2.3</a> erläutert
+und die erweiterte <a href="index_f.html#ixb100078"><font color=#000080><tt>for</tt></font></a>-Schleife
+in <a href="k100043.html#dieforschleife">Abschnitt 6.3.3</a>. Auch
+die variablen Parameterlisten sind eine Neuerung der J2SE 5.0; sie
+werden in <a href="k100049.html#variableparameterlisten">Abschnitt 7.3.4</a>
+erläutert.
+
+<!-- Section -->
+
+<a name="sectlevel3id015008002"></a>
+<h3>15.8.2 Collections mit mehreren Typparametern </h3>
+
+<p>
+Wie bereits erwähnt können auch Collections typsicher gemacht
+werden, deren Methoden üblicherweise mehr als einen Parameter
+erwarten. Ein gutes Beispiel dafür ist das Interface <a href="index_m.html#ixb100718"><font color=#000080><tt>Map</tt></font></a>
+und dessen implementierende Klassen (etwa <a href="index_h.html#ixb100121"><font color=#000080><tt>HashMap</tt></font></a>,
+<a href="index_t.html#ixb100764"><font color=#000080><tt>TreeMap</tt></font></a>
+oder <a href="index_h.html#ixb100419"><font color=#000080><tt>Hashtable</tt></font></a>).
+Sie speichern nicht einzelne Werte, sondern Schlüssel-Wert-Paare.
+Soll eine solche Klasse typsicher verwendet werden, sind bei der Deklaration
+zwei Typ-Parameter anzugeben:
+<font color="#000077">
+<pre>
+Hashtable<String, Integer> h = new Hashtable<String, Integer>();
+</pre>
+</font>
+
+<p>
+An die Einfügeoperationen, die beide Parameter erwarten, muss
+nach einer solchen Deklaration zwangsweise ein String und ein Integer
+übergeben werden. Die Zugriffsmethoden dagegen erwarten einen
+<a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
+als Schlüssel und liefern einen <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>
+als Rückgabewert. Beispielhaft wollen wir uns eine Methode ansehen,
+die eine Liste von Strings erwartet und dann zählt, wie oft jedes
+einzelne Wort darin vorkommt. Eine Pre-5.0-Implementierung könnte
+so aussehen:
+<a name="listingid015011"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> wordCount1(String[] args)
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> Hashtable h = <font color="#0000AA">new</font> Hashtable();
+<font color="#555555">004 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i < args.length; ++i) {
+<font color="#555555">005 </font> <font color="#006699">int</font> cnt = 1;
+<font color="#555555">006 </font> <font color="#0000AA">if</font> (h.containsKey(args[i])) {
+<font color="#555555">007 </font> cnt = 1 + ((Integer)h.get(args[i])).intValue();
+<font color="#555555">008 </font> }
+<font color="#555555">009 </font> h.put(args[i], <font color="#0000AA">new</font> Integer(cnt));
+<font color="#555555">010 </font> }
+<font color="#555555">011 </font> System.out.println(h);
+<font color="#555555">012 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 15.11: Ein untypisierter Wortzähler</i></p>
+
+<p>
+Für jedes Element des Parameter-Arrays wird geprüft, ob
+es schon in der <a href="index_h.html#ixb100419"><font color=#000080><tt>Hashtable</tt></font></a>
+<font color="#000077"><tt>h</tt></font> enthalten ist. Ist das der
+Fall, wird das Wort als Schlüssel verwendet, der zugehörige
+Zählerstand aus <font color="#000077"><tt>h</tt></font> gelesen
+und um 1 erhöht. Ist das nicht der Fall, wird der Zähler
+mit 1 initialisiert. Anschließend wird der Zählerwert mit
+dem Wort als Schlüssel in die Hashtable geschrieben.
+
+<p>
+Seit der J2SE 5.0 kann man die Methode stark vereinfachen:
+<a name="zweifachtypsicher"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> wordCount2(String... args)
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> Hashtable<String, Integer> h = <font color="#0000AA">new</font> Hashtable<String, Integer>();
+<font color="#555555">004 </font> <font color="#0000AA">for</font> (String key : args) {
+<font color="#555555">005 </font> <font color="#0000AA">if</font> (h.containsKey(key)) {
+<font color="#555555">006 </font> h.put(key, 1 + h.get(key));
+<font color="#555555">007 </font> } <font color="#0000AA">else</font> {
+<font color="#555555">008 </font> h.put(key, 1);
+<font color="#555555">009 </font> }
+<font color="#555555">010 </font> }
+<font color="#555555">011 </font> System.out.println(h);
+<font color="#555555">012 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 15.12: Die 5.0-Wortzählervariante</i></p>
+
+<p>
+Auch hier machen wir uns gleich alle drei oben genannten Erweiterungen
+der J2SE 5.0 zu Nutze. Zudem gibt es einen weiteren Vorteil. Da nun
+die Datentypen der Methoden <a href="index_p.html#ixb100698"><font color=#000080><tt>put</tt></font></a>
+und <a href="index_g.html#ixb100699"><font color=#000080><tt>get</tt></font></a>
+bekannt sind, können wir - dank der Verkürzung durch Autoboxing
+und Autounboxing - die Programmstruktur übersichtlicher machen.
+Wir schreiben dazu die <a href="index_p.html#ixb100698"><font color=#000080><tt>put</tt></font></a>-
+und <a href="index_g.html#ixb100699"><font color=#000080><tt>get</tt></font></a>-Operationen
+in eine Zeile, die Hilfsvariable <font color="#000077"><tt>cnt</tt></font>
+wird gar nicht mehr gebraucht.
+
+<!-- Section -->
+
+<a name="eigenetypisiertelistenklasse"></a>
+<h3>15.8.3 Eine eigene typisierte Listenklasse </h3>
+
+<p>
+Nachdem wir uns in den vorherigen Abschnitten angesehen haben, wie
+generische Collections verwendet werden, wollen wir nun eine eigene
+generische Listenklasse implementieren. Deren Interface soll bewußt
+schlank gehalten werden, um unnötige Verkomplizierungen zu vermeiden.
+Es besteht aus je einer Methode, um Elemente einzufügen und auszulesen,
+einer Methode zur Abfrage der Größe und aus einem Iterator,
+um die Elemente (u.a. mit den neuen foreach-Schleifen der J2SE 5.0)
+durchlaufen zu können.
+
+<p>
+Der Einfachheit halber wollen wir die Liste mit einem Array als interne
+Datenstruktur realisieren und definieren dazu folgende Klasse:
+<a name="listingid015013"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">import</font> java.util.*;
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#00AA00">/**
+<font color="#555555">004 </font> * Die folgende Klasse realisiert eine einfache Liste mit einer
+<font color="#555555">005 </font> * festen Größe. Die Liste kann typisiert werden, so dass
+<font color="#555555">006 </font> * Zugriffs- und Hinzufügemethoden typsicher werden. Darüber
+<font color="#555555">007 </font> * hinaus implementiert sie das Interface Iterable und stellt
+<font color="#555555">008 </font> * einen typsicheren Iterator zur Verfügung, um die Verwendung
+<font color="#555555">009 </font> * in J2SE-5.0-foreach-Schleifen zu ermöglichen.
+<font color="#555555">010 </font> */</font>
+<font color="#555555">011 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> MiniListe<E>
+<font color="#555555">012 </font><font color="#0000AA">implements</font> Iterable<E>
+<font color="#555555">013 </font>{
+<font color="#555555">014 </font> <font color="#0000AA">private</font> Object[] data;
+<font color="#555555">015 </font> <font color="#0000AA">private</font> <font color="#006699">int</font> size;
+<font color="#555555">016 </font>
+<font color="#555555">017 </font> <font color="#00AA00">/**
+<font color="#555555">018 </font> * Erzeugt eine leere Liste, die maximal maxSize Elemente
+<font color="#555555">019 </font> * aufnehmen kann.
+<font color="#555555">020 </font> */</font>
+<font color="#555555">021 </font> <font color="#0000AA">public</font> MiniListe(<font color="#006699">int</font> maxSize)
+<font color="#555555">022 </font> {
+<font color="#555555">023 </font> <font color="#006699">this</font>.data = <font color="#0000AA">new</font> Object[maxSize];
+<font color="#555555">024 </font> <font color="#006699">this</font>.size = 0;
+<font color="#555555">025 </font> }
+<font color="#555555">026 </font>
+<font color="#555555">027 </font> <font color="#00AA00">/**
+<font color="#555555">028 </font> * Fügt ein Element zur Liste hinzu. Falls diese schon
+<font color="#555555">029 </font> * voll ist, wird eine Exception ausgelöst.
+<font color="#555555">030 </font> */</font>
+<font color="#555555">031 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> addElement(E element)
+<font color="#555555">032 </font> {
+<font color="#555555">033 </font> <font color="#0000AA">if</font> (size >= data.length) {
+<font color="#555555">034 </font> <font color="#0000AA">throw</font> <font color="#0000AA">new</font> ArrayIndexOutOfBoundsException();
+<font color="#555555">035 </font> }
+<font color="#555555">036 </font> data[size++] = element;
+<font color="#555555">037 </font> }
+<font color="#555555">038 </font>
+<font color="#555555">039 </font> <font color="#00AA00">/**
+<font color="#555555">040 </font> * Liefert die Anzahl der Elemente in der Liste.
+<font color="#555555">041 </font> */</font>
+<font color="#555555">042 </font> <font color="#0000AA">public</font> <font color="#006699">int</font> size()
+<font color="#555555">043 </font> {
+<font color="#555555">044 </font> <font color="#0000AA">return</font> size;
+<font color="#555555">045 </font> }
+<font color="#555555">046 </font>
+<font color="#555555">047 </font> <font color="#00AA00">/**
+<font color="#555555">048 </font> * Liefert das Element an Position pos. Falls kein solches
+<font color="#555555">049 </font> * Element vorhanden ist, wird eine Exception ausgelöst.
+<font color="#555555">050 </font> */</font>
+<font color="#555555">051 </font> <font color="#0000AA">public</font> E elementAt(<font color="#006699">int</font> pos)
+<font color="#555555">052 </font> {
+<font color="#555555">053 </font> <font color="#0000AA">if</font> (pos >= size) {
+<font color="#555555">054 </font> <font color="#0000AA">throw</font> <font color="#0000AA">new</font> NoSuchElementException();
+<font color="#555555">055 </font> }
+<font color="#555555">056 </font> <font color="#0000AA">return</font> (E)data[pos];
+<font color="#555555">057 </font> }
+<font color="#555555">058 </font>
+<font color="#555555">059 </font> <font color="#00AA00">/**
+<font color="#555555">060 </font> * Liefert einen Iterator zum Durchlaufen der Elemente.
+<font color="#555555">061 </font> */</font>
+<font color="#555555">062 </font> <font color="#0000AA">public</font> Iterator<E> iterator()
+<font color="#555555">063 </font> {
+<font color="#555555">064 </font> <font color="#0000AA">return</font> <font color="#0000AA">new</font> Iterator<E>()
+<font color="#555555">065 </font> {
+<font color="#555555">066 </font> <font color="#006699">int</font> pos = 0;
+<font color="#555555">067 </font>
+<font color="#555555">068 </font> <font color="#0000AA">public</font> <font color="#006699">boolean</font> hasNext()
+<font color="#555555">069 </font> {
+<font color="#555555">070 </font> <font color="#0000AA">return</font> pos < size;
+<font color="#555555">071 </font> }
+<font color="#555555">072 </font> <font color="#0000AA">public</font> E next()
+<font color="#555555">073 </font> {
+<font color="#555555">074 </font> <font color="#0000AA">if</font> (pos >= size) {
+<font color="#555555">075 </font> <font color="#0000AA">throw</font> <font color="#0000AA">new</font> NoSuchElementException();
+<font color="#555555">076 </font> }
+<font color="#555555">077 </font> <font color="#0000AA">return</font> (E)data[pos++];
+<font color="#555555">078 </font> }
+<font color="#555555">079 </font> <font color="#0000AA">public</font> <font color="#006699">void</font> remove()
+<font color="#555555">080 </font> {
+<font color="#555555">081 </font> <font color="#0000AA">throw</font> <font color="#0000AA">new</font> UnsupportedOperationException();
+<font color="#555555">082 </font> }
+<font color="#555555">083 </font> };
+<font color="#555555">084 </font> }
+<font color="#555555">085 </font>
+<font color="#555555">086 </font> <font color="#00AA00">//------------------------------------------</font>
+<font color="#555555">087 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">088 </font> {
+<font color="#555555">089 </font> <font color="#00AA00">//Untypisierte Verwendung</font>
+<font color="#555555">090 </font> MiniListe l1 = <font color="#0000AA">new</font> MiniListe(10);
+<font color="#555555">091 </font> l1.addElement(3.14);
+<font color="#555555">092 </font> l1.addElement(<font color="#0000FF">"world"</font>);
+<font color="#555555">093 </font> <font color="#0000AA">for</font> (Object o : l1) {
+<font color="#555555">094 </font> System.out.println(o);
+<font color="#555555">095 </font> }
+<font color="#555555">096 </font> <font color="#00AA00">//Ganzzahlige Typisierung</font>
+<font color="#555555">097 </font> System.out.println(<font color="#0000FF">"---"</font>);
+<font color="#555555">098 </font> MiniListe<Integer> l2 = <font color="#0000AA">new</font> MiniListe<Integer>(5);
+<font color="#555555">099 </font> l2.addElement(3);
+<font color="#555555">100 </font> l2.addElement(1);
+<font color="#555555">101 </font> l2.addElement(4);
+<font color="#555555">102 </font> <font color="#0000AA">for</font> (Integer i : l2) {
+<font color="#555555">103 </font> System.out.println(i + 1000);
+<font color="#555555">104 </font> }
+<font color="#555555">105 </font> <font color="#00AA00">//Verwendung read-only</font>
+<font color="#555555">106 </font> System.out.println(<font color="#0000FF">"---"</font>);
+<font color="#555555">107 </font> MiniListe<? <font color="#0000AA">extends</font> Number> l3 = l2;
+<font color="#555555">108 </font> <font color="#0000AA">for</font> (Number i : l3) {
+<font color="#555555">109 </font> System.out.println(i.intValue() + 1000);
+<font color="#555555">110 </font> }
+<font color="#555555">111 </font> }
+<font color="#555555">112 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/MiniListe.java"><font color="#000055" size=-1>MiniListe.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 15.13: Eine eigene typisierte Listenklasse</i></p>
+
+<p>
+Die Ausgabe des Programms ist:
+<font color="#333300">
+<pre>
+3.14
+world
+---
+1003
+1001
+1004
+---
+1003
+1001
+1004
+</pre>
+</font>
+
+<p>
+Wir wollen uns einige interessante Implementierungsdetails ansehen:
+<ul>
+<li>Zunächst fällt auf, dass bei der Deklaration der Klasse
+ein formaler Typparameter <font color="#000077"><tt>E</tt></font>
+an den Typnamen angehängt wird. Dieser wird beim Einfügen
+und Auslesen von Listenelementen wiederverwendet und steht für
+den Datentyp, mit dem die Klasse später instanziert wird. Er
+sorgt beispielsweise dafür, dass eine <font color="#000077"><tt>MiniListe<Integer></tt></font>
+auch nur <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>-Werte
+aufnehmen und ausgeben kann, nicht aber <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>-,
+<a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-
+oder andere Datentypen. Die Bezeichnung <font color="#000077"><tt>E</tt></font>
+ist eine Namenskonvention, die für »Element« steht,
+bei Schlüssel-Wert-Collections empfiehlt die Java-Dokumentation
+<font color="#000077"><tt>K</tt></font> (für »Key«)
+und <font color="#000077"><tt>V</tt></font> (für »Value«).
+<li>Das Array zur Ablage der Daten ist vom Typ <a name="ixa101018"><a href="index_o.html#ixb100775"><font color=#000080><tt>Object[]</tt></font></a></a>.
+Egal, wie die Liste später typisiert wird, das Array kann die
+eingehenden Werte auf jeden Fall aufnehmen, denn <a href="index_o.html#ixb100224"><font color=#000080><tt>Object</tt></font></a>
+ist Oberklasse aller anderen Klassen.
+<li>Die Methode <font color="#000077"><tt>addElement</tt></font> besitzt
+einem formalen Parameter vom Typ <font color="#000077"><tt>E</tt></font>.
+Damit drücken wir aus, dass beim Aufruf von <font color="#000077"><tt>addElement</tt></font>
+nur solche Elemente übergeben werden können, die dem Typ
+entsprechen, mit dem die Liste deklariert wurde. <font color="#000077"><tt>E</tt></font>
+steht hier als Platzhalter für den Typ, mit dem die Liste instanziert
+wurde und wird überall dort verwendet, wo sichergestellt werden
+soll, dass beim Aufruf der korrekte Typ verwendet wird. Wurde die
+Liste beispielsweise als <font color="#000077"><tt>MiniListe<Integer></tt></font>
+deklariert, steht <font color="#000077"><tt>E</tt></font> für
+<a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>,
+und <font color="#000077"><tt>addElement</tt></font> verhält
+sich, als wäre sie wie folgt deklariert worden:
+<font color="#000077">
+<pre>
+ public void addElement(Integer element)
+
+</pre>
+</font>
+<li>Das gleiche Verfahren wird beim Rückgabewert von <font color="#000077"><tt>elementAt</tt></font>
+angewendet. Damit drücken wir aus, dass auch die Rückgabewerte
+beim Zugriff auf Listenelemente genau den Datentyp haben sollen, mit
+dem die Liste deklariert wurde.
+<li>Der Iterator wird ebenfalls typisiert deklariert, damit er beim
+Durchlaufen der Elemente direkt den richtigen Datentyp liefert. Hier
+kann man erkennen, dass der formale Typparameter nicht nur zur Definition
+von einfachen Methodenparametern und Rückgabewerten sondern auch
+zur typkonformen Deklaration und Instanzierung anderer generischer
+Klassen verwendet werden kann.
+</ul>
+
+<p>
+Damit ist die komplette Schnittstelle der Klasse typsicher, und wir
+können sie wie in den vorigen Abschnitten beschrieben verwenden.
+Die <a href="index_m.html#ixb100150"><font color=#000080><tt>main</tt></font></a>-Methode
+zeigt einige Anwendungen, die nach den bisherigen Ausführungen
+selbsterklärend sein sollten.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Zu beachten ist, dass in diesem Beispiel »nur« die öffentliche
+Schnittstelle der Klasse typsicher ist. Innerhalb der Klasse selbst
+ist es nach wie vor möglich, fehlerhaft typisierte Werte in das
+Datenarray einzufügen, denn als <a href="index_o.html#ixb100775"><font color=#000080><tt>Object[]</tt></font></a>
+kann es beliebige Objekte aufnehmen. Wir könnten eine solche
+Schnittstelle sogar öffentlich machen:
+<font color="#000077">
+<pre>
+public void addStringElement(String s)
+{
+ if (size >= data.length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ data[size++] = s;
+}
+</pre>
+</font>
+
+<p>
+Dieser Code wäre vollkommen korrekt und würde vom Compiler
+nicht beanstandet werden. Ein Aufruf der Methode in einer <font color="#000077"><tt>MiniListe<Double></tt></font>
+würde tatsächlich einen <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
+einfügen, und beim Zugriff auf dieses Element würde es zu
+einer <a href="index_c.html#ixb100729"><font color=#000080><tt>ClassCastException</tt></font></a>
+kommen. »Typsichere« Klassen sind also nur dann wirklich
+typsicher, wenn die Implementierung sicherstellt, dass keine typfremden
+Werte gespeichert werden.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
+<tr>
+<td><font color="#FFFFFF"> Warnung </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+
+<!-- Section -->
+<a name="sectlevel3id015008004"></a>
+<h3>15.8.4 Typkompatibilität </h3>
+
+
+<!-- Section -->
+<a name="sectlevel4id015008004001"></a>
+<h4>Ober- und Unterklassen in generischen Typen </h4>
+
+<p>
+Beim Umgang mit typisierten Collections gibt es einige Besonderheiten,
+die zu einer Verkomplizierung des ursprünglichen Mechanismus
+geführt haben. Wir wollen zunächst eine einfache Methode
+betrachten, um uns noch einmal das Zusammenspiel zwischen Ober- und
+Unterklassen anzusehen (es wurde unter dem Stichwort »Polymorphismus«
+bereits in den Abschnitten <a href="k100047.html#polymorphismus">Abschnitt 7.1.6</a>
+und <a href="k100055.html#abstraktpolymorph">Abschnitt 8.4</a> erläutert):
+<a name="listingid015014"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> doesWork1()
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> Double pi = <font color="#0000AA">new</font> Double(3.14);
+<font color="#555555">004 </font> Number num = pi;
+<font color="#555555">005 </font> System.out.println(num.toString());
+<font color="#555555">006 </font> Double pi2 = (Double)num;
+<font color="#555555">007 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 15.14: Funktionierendes Zusammenspiel von Ober- und Unterklassen</i></p>
+
+<p>
+Zunächst wird eine <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>-Variable
+<font color="#000077"><tt>pi</tt></font> angelegt und mit dem Fließkommawert
+3.14 initialisiert. In der nächsten Zeile machen wir uns die
+Tatsache zunutze, dass <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>
+eine Unterklasse von <a name="ixa101019"><a href="index_n.html#ixb100776"><font color=#000080><tt>Number</tt></font></a></a>
+ist und weisen der Variablen der Oberklasse einen Wert der Unterklasse
+zu. Dies entspricht unserem bisherigen Verständnis von objektorientierter
+Programmierung, denn ein <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>
+<i>ist eine</i> <a href="index_n.html#ixb100776"><font color=#000080><tt>Number</tt></font></a>,
+hat alle Eigenschaften von <a href="index_n.html#ixb100776"><font color=#000080><tt>Number</tt></font></a>
+(und ein paar mehr), und kann daher problemlos als <a href="index_n.html#ixb100776"><font color=#000080><tt>Number</tt></font></a>
+verwendet werden. Die nächsten beiden Zeilen beweisen, dass diese
+Annahme korrekt ist (der Inhalt von <font color="#000077"><tt>num</tt></font>
+ist tatsächlich 3.14) und dass man die <a href="index_n.html#ixb100776"><font color=#000080><tt>Number</tt></font></a>-Variable
+auch zurückkonvertieren kann - in Wirklichkeit zeigt sie ja auf
+ein <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Überträgt man das Beispiel auf typisierte Collections, lassen
+sich die dahinter stehenden Annahmen nicht ohne weiteres aufrecht
+erhalten. Ein <font color="#000077"><tt>Vector<Double></tt></font>
+ist kein Subtyp eines <font color="#000077"><tt>Vector<Number></tt></font>!
+Die folgenden Codezeilen sind illegal und werden vom Compiler abgewiesen:
+<font color="#000077">
+<pre>
+Vector<Double> vd = new Vector<Double>();
+Vector<Number> vn = vd;
+</pre>
+</font>
+</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
+<tr>
+<td><font color="#FFFFFF"> Warnung </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+<p>
+Wir wollen uns ansehen, warum das so ist. Wären sie nämlich
+erlaubt, könnten wir folgende Methode schreiben:
+<a name="listingid015015"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> doesntWork1()
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> Vector<Double> vd = <font color="#0000AA">new</font> Vector<Double>();
+<font color="#555555">004 </font> Vector<Number> vn = vd;
+<font color="#555555">005 </font> vn.addElement(<font color="#0000AA">new</font> Integer(7));
+<font color="#555555">006 </font> Double x = vd.elementAt(0);
+<font color="#555555">007 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 15.15: Nicht funktionierendes Zusammenspiel von Ober- und
+Unterklassen</i></p>
+
+<p>
+Das Programm erzeugt einen <font color="#000077"><tt>Vector<Double>
+vd</tt></font> und weist ihn einer <font color="#000077"><tt>Vector<Number>-Variable
+vn</tt></font> zu. Wäre diese eine Oberklasse von <font color="#000077"><tt>Vector<Double></tt></font>,
+könnten wir natürlich auch <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>-Werte
+in den <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+einfügen wollen. Denn auch <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>
+ist eine Unterklasse von <a href="index_n.html#ixb100776"><font color=#000080><tt>Number</tt></font></a>,
+und mit derselben Berechtigung würden wir annehmen, dass <font color="#000077"><tt>Vector<Number></tt></font>
+Oberklasse von <font color="#000077"><tt>Vector<Integer></tt></font>
+ist. Dann wäre aber nicht mehr sichergestellt, dass beim Zugriff
+auf <font color="#000077"><tt>vd</tt></font> nur noch <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>-Elemente
+geliefert werden, denn über den Umweg <font color="#000077"><tt>vn</tt></font>
+haben wir ja auch ein <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>-Objekt
+eingefügt. Der Compiler könnte also nicht mehr garantieren,
+dass die vierte Zeile korrekt ausgeführt wird.
+
+<p>
+Daraus ist ein folgenschwerer Schluß zu ziehen: Ist <font color="#000077"><tt>U</tt></font>
+eine Unterklasse von <font color="#000077"><tt>O</tt></font>, so folgt
+daraus <i>eben nicht</i>, dass auch <font color="#000077"><tt>G<U></tt></font>
+eine Unterklasse von <font color="#000077"><tt>G<O></tt></font>
+ist. Das ist schwer zu verstehen, denn es widerspricht unseren bisherigen
+Erfahrungen im Umgang mit Ober- und Unterklassen. Das Problem dabei
+ist die <i>Veränderlichkeit</i> des Vectors, denn dadurch könnte
+man über den Alias-Zeiger <font color="#000077"><tt>vn</tt></font>
+Werte einzufügen, die nicht typkonform sind. Aus diesem Grunde
+würde der Compiler bereits die zweite Zeile der obigen Methode
+mit einem Typfehler ablehnen.
+
+<!-- Section -->
+
+<a name="sectlevel4id015008004002"></a>
+<h4>Der Wildcard ?<a name="ixa101020"></a><a name="ixa101021"></a>
+</h4>
+
+<p>
+Diese neue Typinkompatibilität hat nun einige Konsequenzen, die
+sich vor allem dort bemerkbar machen, wo wir bisher intuitiv angenommen
+haben, dass Ober- und Unterklasse zuweisungskompatibel sind. Ein Beispiel
+ist etwa die Parametrisierung von Methoden, bei der man üblicherweise
+die formalen Parameter etwas allgemeiner fasst, um die Methode vielseitiger
+einsetzen zu können.
+
+<p>
+Betrachten wir eine Methode zur Ausgabe aller Elemente unserer Zahlenliste.
+Mit etwas Weitblick würde man sie so formulieren:
+<a name="listingid015016"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> printAllNumbers1(List<Number> numbers)
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> <font color="#0000AA">for</font> (Number s : numbers) {
+<font color="#555555">004 </font> System.out.println(s);
+<font color="#555555">005 </font> }
+<font color="#555555">006 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 15.16: Nicht funktionierende Ausgabe der Zahlenliste</i></p>
+
+<p>
+Anstelle eines <font color="#000077"><tt>Vector<Double></tt></font>
+verallgemeinern wir auf <font color="#000077"><tt>List<Number></tt></font>.
+In der Annahme, dann nicht nur den Inhalt eines Vektors ausgeben zu
+können, sondern auch den einer <a href="index_a.html#ixb100719"><font color=#000080><tt>ArrayList</tt></font></a>
+oder <a href="index_l.html#ixb100695"><font color=#000080><tt>LinkedList</tt></font></a>
+(die beide ebenfalls vom Typ <a href="index_l.html#ixb100717"><font color=#000080><tt>List</tt></font></a>
+sind), und zwar auch dann, wenn sie nicht <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>-,
+sondern auch <a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>-
+oder <a href="index_l.html#ixb100467"><font color=#000080><tt>Long</tt></font></a>-Werte
+enthalten (die ebenfalls vom Typ <a href="index_n.html#ixb100776"><font color=#000080><tt>Number</tt></font></a>
+sind). Diese Methode enthält nicht mehr Code als die speziellere
+Form, ist aber viel universeller einzusetzen. Ergo würde sich
+ein erfahrener Programmierer normalerweise dafür entscheiden,
+sie auf diese Weise zu parametrisieren.
+
+<p>
+Leider hat die Sache einen Haken. Zwar akzeptiert <font color="#000077"><tt>printAllNumbers1</tt></font>
+beliebige Collections vom Typ <a href="index_l.html#ixb100717"><font color=#000080><tt>List</tt></font></a>,
+aber eben nur, wenn sie Werte vom Typ <a href="index_n.html#ixb100776"><font color=#000080><tt>Number</tt></font></a>
+enthalten. Solche mit <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>-,
+<a href="index_i.html#ixb100170"><font color=#000080><tt>Integer</tt></font></a>-
+oder <a href="index_l.html#ixb100467"><font color=#000080><tt>Long</tt></font></a>-Werten
+lehnt sie - aus den oben beschriebenen Gründen - ab. Der praktische
+Nutzen dieser Methode ist damit nur mehr gering.
+
+<p>
+Um mehr Flexibilität zu gewinnen, wurde der Wildcard »?«
+als Typparameter eingeführt. Wird das Fragezeichen anstelle eines
+konkreten Elementtyps angegeben, bedeutet dies, das die Collection
+beliebige Werte enthalten kann:
+<a name="listingid015017"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> printAllNumbers2(List<?> numbers)
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> <font color="#0000AA">for</font> (Object o: numbers) {
+<font color="#555555">004 </font> System.out.println(o);
+<font color="#555555">005 </font> }
+<font color="#555555">006 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 15.17: Funktionierende Ausgabe der Zahlenliste</i></p>
+
+<p>
+An diese Methode können nun Listen mit beliebig typisierten Elementen
+übergeben werden. Allerdings gibt es beim Lesen der Elemente
+keine Typsicherheit mehr. Am Kopf der <a href="index_f.html#ixb100078"><font color=#000080><tt>for</tt></font></a>-Schleife
+kann man erkennen, dass der Compiler die Listenelemente nun - wie
+in früheren JDK-Versionen - lediglich als Werte des Typs <a href="index_o.html#ixb100224"><font color=#000080><tt>Object</tt></font></a>
+ansieht. Spezielle Eigenschaften sind damit unsichtbar bzw. müssen
+mit Hilfe einer expliziten Typkonvertierung wieder sichtbar gemacht
+werden.
+
+<!-- Section -->
+
+<a name="sectlevel4id015008004003"></a>
+<h4><a name="ixa101022">Gebundene Wildcards</a><a name="ixa101023"></a></h4>
+
+<p>
+Eine abgeschwächte Form des »?«-Wildcards sind die
+gebundenen Wildcards (»bounded wildcards«). Sie entstehen,
+wenn nach dem Fragezeichen das Schlüsselwort <a name="ixa101024"><a href="index_e.html#ixb100416"><font color=#000080><tt>extends</tt></font></a></a>
+angegeben wird, gefolgt vom Namen des Elementtyps. Dadurch wird ausgedrückt,
+dass die Collection Elemente der angegebenen Klasse oder einer ihrer
+Unterklassen enthalten kann:
+<a name="listingid015018"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> printAllNumbers3(List<? <font color="#0000AA">extends</font> Number> numbers)
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> <font color="#0000AA">for</font> (Number s : numbers) {
+<font color="#555555">004 </font> System.out.println(s.doubleValue());
+<font color="#555555">005 </font> }
+<font color="#555555">006 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 15.18: Verbesserte funktionierende Ausgabe der Zahlenliste</i></p>
+
+<p>
+Gebundene Wildcards realisieren am ehesten die bisher bekannten Regeln
+von Typkonformität bei Ober- und Unterklassen von Elementen.
+<font color="#000077"><tt>? extends O</tt></font> bedeutet, dass die
+Collection Elemente des Typs <font color="#000077"><tt>O</tt></font>
+oder einer (auch über mehrere Stufen) daraus abgeleiteten Unterklasse
+enthalten kann. An einen formalen Parameter vom Typ <font color="#000077"><tt>List<?
+extends Number></tt></font> können also aktuelle Parameter
+des Typs <font color="#000077"><tt>Vector<Double></tt></font>,
+<font color="#000077"><tt>ArrayList<Integer></tt></font> usw.
+übergeben werden.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Zu beachten ist allerdings, dass die Wildcards nur das <i>Lesen</i>
+der Elemente flexibilisieren. Das Einfügen neuer Elemente ist
+dagegen <i>nicht mehr erlaubt</i> und wird vom Compiler unterbunden.
+Genauer gesagt, verboten ist der Aufruf von Methoden, die mindestens
+einen generisch typisierten Parameter haben. Die Gründe entsprechen
+den oben erläuterten. Wäre es nämlich zulässig,
+in eine <font color="#000077"><tt>List<? extends Number></tt></font>
+einen <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>
+einzufügen, so würde ein Problem entstehen, wenn es sich
+tatsächlich beispielsweise um einen <font color="#000077"><tt>Vector<Integer></tt></font>
+handeln würde, denn dieser darf ja kein Element des Typs <a href="index_d.html#ixb100255"><font color=#000080><tt>Double</tt></font></a>
+aufnehmen. Daher sorgt der Compiler dafür, dass bei der Verwendung
+von Wildcards und gebundenen Wildcards die Collection nur noch zum
+Lesen der Elemente verwendet werden darf. Versuche, neue Elemente
+einzufügen, werden mit einem Compilerfehler quittiert.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
+<tr>
+<td><font color="#FFFFFF"> Hinweis </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+
+<!-- Section -->
+<a name="sectlevel3id015008005"></a>
+<h3>15.8.5 Sonstiges </h3>
+
+<p>
+Die Implementierung von generischen Collections ist in Java im Prinzip
+Sache des Compilers, die virtuelle Maschine merkt davon nichts. Der
+Compiler interpretiert den Quelltext, prüft die Typ-Parameter
+und erzeugt Bytecode mit den erforderlichen Typ-Konvertierungen, Warnungen
+und Fehlermeldungen. Das Laufzeitsystem, die virtuelle Maschine, arbeitet
+dabei im Grunde wie in früheren JDK-Versionen. Dabei bleibt insbesondere
+die Integrität der VM stets erhalten und Typfehler führen
+zu kontrollierten (ClassCast-) Exceptions, wie in früheren JDK-Versionen.
+Trotz allen Aufwands lassen sich nämlich Fälle konstruieren,
+bei denen fehlerhaft typisierte Werte in eine generische Collection
+eingefügt werden. Wir werden dazu im nächsten Abschnitt
+ein einfaches Beispiel sehen.
+
+<p>
+Anders als Templates in C++ erzeugen generische Java-Klassen keinen
+zusätzlichen Programmcode. Alle Instanzen einer generischen Klasse
+verwenden denselben Bytecode, <a name="ixa101025"><a href="index_g.html#ixb100781"><font color=#000080><tt>getClass</tt></font></a></a>
+liefert ein und dasselbe Klassenobjekt und die statischen Variablen
+werden gemeinsam verwendet. Es ist nicht erlaubt, in statischen Initialisierern
+oder statischen Methoden auf den Typparameter einer Klasse zuzugreifen,
+und die Anwendung des <a name="ixa101026"><a href="index_i.html#ixb100330"><font color=#000080><tt>instanceof</tt></font></a></a>-Operators
+auf eine typisierte Klasse ist illegal.
+
+<p>
+Es ist zulässig, generische Collections und herkömmliche
+Collections gemeinsam zu verwenden. Erwartet beispielsweise ein Methodenparameter
+eine typisierte Collection, so kann auch eine untypisierte Collection
+übergeben werden, und umgekehrt. In diesem Fall kann der Compiler
+die Typsicherheit des Programmcodes allerdings nicht mehr sicherstellen
+und generiert vorsichtshalber eine »unchecked warning« <a name="ixa101027"></a>:
+<font color="#333300">
+<pre>
+Note: Some input files use unchecked or unsafe operations.
+Note: Recompile with -Xlint:unchecked for details.
+</pre>
+</font>
+
+<p>
+Durch Rekompilieren mit <a name="ixa101028"><a href="index_0.html#ixb100783"><font color=#000080><tt>-Xlint:unchecked</tt></font></a></a>
+werden Detailinformationen ausgegeben. Die Entwickler des JDK gehen
+davon aus, dass in Zukunft nur noch typisierte Collections verwendet
+werden, und diese Warnungen nach einer gewissen Übergangszeit
+der Vergangenheit angehören werden.
+
+<p>
+Neben den hier beschriebenen Eigenschaften gibt es noch eine ganze
+Reihe weiterer Aspekte von generischen Klassen, auf die wir hier nicht
+näher eingehen wollen. Sie werden meist gebraucht, um spezielle
+Sonderfälle bei der Entwicklung von Collection-Klassen zu realisieren;
+für »Otto Normalprogrammierer« sind die meisten von
+ihnen weniger relevant. Die nachfolgende Aufzählung listet einige
+von ihnen auf, weitere Informationen können der Sprachspezifikation
+bzw. der Dokumentation der J2SE 5.0 oder 6.0 entnommen werden:
+<ul>
+<li>Mit dem Schlüsselwort <a name="ixa101029"><a href="index_s.html#ixb100424"><font color=#000080><tt>super</tt></font></a></a>
+können gebundene Wildcards mit unteren Grenzen definiert werden.
+<font color="#000077"><tt>List<? super Number></tt></font> ist
+eine Liste von Objekten des Typs <a href="index_n.html#ixb100776"><font color=#000080><tt>Number</tt></font></a>
+oder einer beliebigen Oberklasse von <a href="index_n.html#ixb100776"><font color=#000080><tt>Number</tt></font></a>.
+<li>Mit Hilfe des &-Operators können mehrfache Bindungen
+angegeben werden (»multiple bounds« <a name="ixa101030"></a>).
+Ein derart spezifizierter Typ ist Subtyp aller angegebenen Typen.
+<li>Neben generischen Klassen können auch <a name="ixa101031">generische Methoden</a>
+definiert werden. Sie erhalten einen expliziten Typ-Parameter, der
+in Aufruf- und Rückgabeparametern verwendet werden kann. Anders
+als bei typisierten Klassen muss dieser bei Aufruf der Methode nicht
+explizit angegeben werden, sondern wird vom Compiler automatisch hergeleitet.
+</ul>
+<hr>
+<table border=0 cellpadding=0 cellspacing=1 width="100%">
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
+<td align="right">Handbuch der Java-Programmierung, 5. Auflage, Addison
+Wesley, Version 5.0.1
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100097.html"> << </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100104.html"> < </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100106.html"> > </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100107.html"> >> </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
+<td align="right">© 1998, 2007 Guido Krüger & Thomas
+Stark, <a href="http://www.javabuch.de">http://www.javabuch.de</a>
+</table>
+<a name="endofbody"></a>
+</body>
+</html>
|
