Generics in Java 1.5

 


... [ Seminar BS, WWW und Java ] ... [ Thema Generics in Java ] ... [ Erste Beispiele ] ...

Einführung


Was sind Generics?

Generics bzw. Generizität und generische Elemente sind ein Sprachmittel von Programmiersprachen. Im Falle von Java heißt dies, dass Klassen und Methoden (Methoden auch außerhalb von parametrisierten Klassen) mit Typparametern parametrisiert werden können. Es geht also u. a. um Konstrukte wie einen "Vector of String", also einen Vector, der nur String-Objekte aufnehmen kann.

Aus anderen Programmiersprachen sind vergleichbare Konzepte bekannt, teilweise unter anderen Namen. In C++ gibt es die Template-Klassen, also Schablonenklassen. Auch wenn diese syntaktisch einige Ähnlichkeit zu den Generics in Java haben, arbeiten diese völlig anders.
In der funktionalen Programmiersprache Haskell ist die Generizität ein integraler Teil der Sprache. Hier sind Typparameter, im Gegensatz zu Java, sogar häufig obligatorisch, dürfen also nicht weggelassen werden. Ein Adressbuch könnte man in Haskell z. B. wie folgt definieren:
1: type Adressbuch = Map Name Adresse
2: type Name = String
3: type Adresse = (...)
Hier sind die Typen Name (ein Alias für den Typ String) sowie Adresse (ein nicht näher definiertes Tupel) Parameter für den Typ Map, d. h. es handelt sich um eine spezielle Ausprägung einer Map.

Gründe für Generics

Einer der Hauptgründe für die Einführung von Generics mit der Java-Version 1.5 ("Tiger") war der Wunsch, die existierenden Containerklassen wie z. B. Vector, Map, Set weiterhin wiederverwendbar zu halten, aber diese um Typsicherheit zu erweitern. So waren vor der Java-Version 1.5 häufig sogenannte Downcasts (explizite Verwendung eines spezielleren Typs für ein Objekt) nötig, wenn man die Objekte aus einem Container auslesen wollte. Hierzu ein Beispiel, wie die Summation einer Liste von Integern ohne Generics üblicherweise realisiert wurde:
1: List intList = new Vector();
2: intList.add(new Integer(1234));
3: intList.add(new Integer(5678));
4: intList.add(new Integer(4711));
5:
6: // Addition aller Werte
7: int sum = 0;
8: for(int i=0;i<intList.size();i++) {
9: sum += ((Integer)intList.get(i)).intValue(); // unkontrollierter Downcast!
10: }
In Zeile 9 wird hier das aktuelle Element der Liste mit der Methode get() ausgelesen. Diese Methode liefert jedoch ein Objekt vom Typ Object, so dass sein Zahlenwert nicht direkt auszulesen ist (es könnte ja auch ein String sein). Daher musste der Programmierer hier einen Downcast (in diesem Falle auf den Typ Integer) vornehmen, um die Methode intValue() aufrufen und somit den Zahlenwert auslesen zu können.
Dies war bei einem kleinen, übersichtlichen Codefragment wie dem obigen natürlich ohne große Probleme möglich; der Programmierer hatte eben dafür zu sorgen, dass nur Integer-Objekte in der Liste landen.
Sollte aber nun diese Funktionalität durch eine Methode in einer Bibliothek zur Verfügung gestellt werden, musste eine manuelle Typüberprüfung durchgeführt werden, da der Programmierer der Bibliotheksfunktion nicht mehr sicherstellen konnte, dass seine Methode wirklich nur mit Integer-Objekten aufgerufen wird:
1: public int sum(List intList) {
2: int result = 0;
3: for(int i=0;i<intList.size();i++) {
4: Object o = intList.get(i);
5: if(o instanceof Integer) // Typüberprüfung
6: result += ((Integer)o).intValue(); // "sicherer" Downcast
7: else
8: throw new IllegalArgumentException("Keine Liste von Integern!");
9: }
10: return result;
11: }
Auch hier sind die Nachteile schnell ersichtlich. Es ist ein beträchtlicher Teil des Codes nur für die Typüberprüfung nötig, und bei mehreren Funktionen würde dieser Code immer wieder benötigt werden. Außerdem wird, im Falle eines Objekts vom falschen Typ in der Liste, eine Exception erst zur Laufzeit ausgelöst. Daher ist die aufrufende Funktion auch noch für eine Fehlerbehandlung verantwortlich, soll das Programm nicht mit einer Exception abstürzen.

Dies alles führte zu der Motivation, eine Technik zur Typsicherheit in Java einzubauen, die Typverletzungen bereits zur Compilezeit meldet. Wie sich dies z. B. auf diese Summations-Funktion auswirkt, wird im nächsten Kapitel gezeigt.

... [ Seminar BS, WWW und Java ] ... [ Thema Generics in Java ] ... [ Einführung ] ... [ Erste Beispiele ] ...