• Keine Ergebnisse gefunden

Vorlesung Informatik 2

N/A
N/A
Protected

Academic year: 2022

Aktie "Vorlesung Informatik 2"

Copied!
17
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Vorlesung Informatik 2

Fachhochschule für Technik Esslingen Studiengang Wirtschaftsinformatik

Generics

Dr. rer. nat. Andreas Rau

???

???

(2)

Dieser Foliensatz erklärt das mit Java 5 eingeführte Sprachfeature "Generics".

Erinnern Sie sich noch an die Warnung

Note: Foo.java uses unchecked or unsafe operations.

Note: Recompile with -Xlint:unchecked for details.

In diesem Teil der Vorlesung erfahren Sie, wo diese Warnung herkommt.

Inhalt

(3)

Hintergrund

Mit Hilfe der Klasse Object und der Vererbungshierarchie darunter ist es möglich, universelle Algorithmen und Datenstrukturen für vielfältige Objekte zu implementieren. Allerdings geht dabei die Typsicherheit teilweise verloren. Eine Einschränkung auf einen bestimmten Typ ist nur durch zusätzliche Schreibarbeit (Prüfungen, Kapselung) möglich. Um solche Nachteile zu umgehen, bieten viele mit Java vergleichbare Programmiersprachen Mechanismen wie z.B. Templates an.

Generics(1)

(4)

Bedeutung

Ein Template ist eine Vorlage oder Schablone für eine Familie von Algorithmen bzw. Datenstrukturen. Dabei steht die Struktur schon exakt fest. Lediglich einige Typangaben sind mit Hilfe von Platzhaltern formuliert und werden erst bei der Verwendung der Vorlage durch einen konkreten Typ ersetzt. Praktisch bedeutet dies, dass der Compiler „die Vorlage unter Verwendung des angegebenen Typs nochmal abschreibt“

und übersetzt.

In Java heißt der entsprechende Mechanismus Generics. Damit lassen sich keine Templates sondern sogenannte parametrisierte Typen definieren. Diese werden nicht wie Templates mehrfach instantiiert sondern nur zur Übersetzungszeit mit zusätzlichen Prüfungen überwacht.

Das Prinzip ist ähnlich, jedoch wird auf diese Art und Weise wesentlich weniger Code erzeugt.

Generics(2)

(5)

Quellcode mit Typparameter

Generics(2a)

Deklaration mit Typparameter Quellcode mit

Typparameter Ausprägung

für String

Quellcode für Basistyp Object

Template, in Sprachen ohne Basistyp

String Adapter

String Adapter

Generics, in Sprachen mit Basistyp

In den Adaptern steckt "normaler"

Java Code. Die Collection arbeitet im class-File also mit Object. Dies nennt man type-erasure.

(6)

Als syntaktischer Zucker werden solche Sprachelemente bezeichnet, die dem Programmierer keine (grundlegend) neuen Möglichkeiten bieten, sondern die vorhandenen Möglichkeiten auf eine kürzere, bequemere oder sicherere Art verpacken bzw. zugänglich machen.

Eine Vielzahl der Neuerungen in Java 5 bestand aus solchen syntaktischen Zucker, z.B. enums, for-each und eben die Generics.

Gleichwohl war diese Version ein großer Schritt nach vorne, da die Programme durch die neuen Elemente kürzer und klarer werden und die Programmierer so mehr Zeit für wichtigere Problemstellungen haben

Was ist syntaktischer Zucker?

(7)

Beispiel (ohne Generics)

// (1) Keine Prüfung beim Befüllen List liste = new ArrayList();

liste.add( "Test");

liste.add( new Integer(1)); // möglicherweise nicht gewollt!

// ...

// (2) Zugriff erfordert Cast (kann schiefgehen) String s1 = (String)liste.get(0);

String s2 = (String)liste.get(1); // Laufzeitfehler // (3) Schleifen sind "unbequem"

for ( Object o : liste) { String s = (String)o;

// ...

}

Iterator iter = liste.iterator();

while ( iter.hasNext()) {

String s = (String)iter.next();

}

Generics(2a)

unchecked or unsafe operations

(8)

Beispiel (mit Generics)

// (1) Prüfung beim Befüllen

List<String> liste = new ArrayList<String>();

liste.add( "Test");

liste.add( new Integer(1)); // Compile-Fehler // ...

// (2) Zugriff ohne Cast (klappt immer) String s1 = liste.get(0);

String s2 = liste.get(1);

// (3) Schleifen sind nicht mehr "unbequem"

for ( String s : liste) { // ...

}

Iterator<String> iter = liste.iterator();

while ( iter.hasNext()) {

Generics(2a)

(9)

Durch die Einführung der Generics gewinnt man also eine Menge an Sicherheit und spart (Schreib)arbeit ohne dabei Flexibilität zu verlieren.

siehe dazu auch

http://java.sun.com/developer/technicalArticles/J2SE/generics/

Die Hauptanwendung von Generics liegt bei den Collections oder allgemeiner ausgedrückt, bei Algorithmen die "Objekte bewegen ohne sie näher kennen zu müssen". Diese sind in der Klassenbibliothek an dem Typparameter erkennbar, z.B. ArrayList<E> oder HashMap<K,V> oder an Interfaces wie Comparator<T>.

Als Programmierer ist man daher meist nur Anwender von Collections. Es ist jedoch auch möglich, eigene generische Strukturen zu implementieren und dabei den Typparameter ggf. auch einzuschränken.

Generics(2c)

(10)

Implementierung einer generischen Klasse

Um eine generische Klasse zu schreiben, gibt man bei der Definition einen oder mehrere Platzhalter für Datentypen an. Diese werden bei der Deklaration(=Verwendung) durch reale Datentypen ersetzt.

Beispiel für Implementierung

public class Capsule<E> { // generische Klasse E value;

public Capsule( E value) { this.value = value;

}

public E getValue() { return value;

}}

Beispiel für Verwendung

Generics(3a)

(11)

Implementierung einer generischen Methode

Man kann auch einzelne Methoden generisch machen – auch in nicht generischen Klassen. Um eine generische Methode zu verwenden, kann man diese ohne Angabe eines Typparameters einfach aufrufen. Der Compiler ermittelt den Typ dann selbstständig aus den Parametern.

Beispiel

public class ListHelper { // erzeugt eine Liste mit Startwerten public static <T> List<T> create( int count, T value) {

List<T> list = new ArrayList<T>();

for ( int i=0; i<count; ++i) { list.add( value);

}

return list;

}}

List<String> sList = ListHelper.create( 10, "");

List<Integer> iList = ListHelper.create( 5, new Integer(0));

Generics(3b)

(12)

Rolle des Typparameters

Wie die Parameter einer Funktion, die als Platzhalter für die Beschreibung von Abläufen und Berechnungen verwendet werden (Man beschreibt anhand der Platzhalter, wie später die tatsächlichen Werte verwendet werden) dient der Typparameter als Platzhalter für einen (bewußt) noch unbekannten Typ bei der Beschreibung einer Klasse oder Methode (Man beschreibt anhand des Platzhalters, welche Werte welchen Typ haben).

Als Konvention gilt dabei, dass für den Typparameter der grossgeschriebene Anfangsbuchstabe seiner Bedeutung verwendet wird (E wie Element, K wie Key, V wie Value, T wie Typ, ...). Bei mehreren Typparametern kann es ggf. auch sinnvoll sein, diese Bedeutung zusätzlich im (Javadoc)Kommentar zu vermerken.

Generics(3c)

(13)

Typverträglichkeiten von generischen Collections

Für einfache Variablen gilt das Prinzip der Polymorphie.

Person p = new Student(); // geht

Bei Collections funktioniert dies nicht ganz so wie zunächst erwartet.

List<Person> = new ArrayList<Student>(); // geht nicht

Warum geht das nicht, obwohl Student doch von Person erbt? Ein Beispiel...

List<Student> ls = new ArrayList<Student>();

List<Person> lp = ls;

lp.add( new Person( "karl", "killer"));

Student s = ls.get(0); // Exception! Kein Student

Nach Zuweisung an eine Liste der Superklasse könnte man also eine Liste der Subklasse "verschmutzen" und so die Typsicherheit zerstören!

Generics(4)

(14)

Einschränkung des Typparameters

Mit Generics kann man noch viel mehr machen! So kann man z.B. die möglichen Typen bei eigenen Klassen durch sog. Bounds einschränken.

Beispiele: Visualisierung siehe die nächsten beiden Folien

Verwendung einer obere Schranke

public class Upper<T extends Person> { /* ... */ } // Upper Bound

Der Typparameter T muss mit einer Klasse belegt werden, die eine Person ist.

Verwendung einer untere Schranke

public class Lower<T super Student> { /* ... */ } // Lower Bound

Generics(4)

(15)

Generics(4a) Object

Thing Lifeform

Vehicle Person Animal

Worker Teilbaum

<T extends Person> Student

(16)

Generics(4b) Object

Thing Lifeform

Vehicle Person Animal

Pfad

(17)

Wildcards

Um Methoden mit generischen Parametern möglichst vielseitig einsetzen zu können kann man statt konkreten Typparametern auch sog. Wildcards verwenden. Dabei steht die Wildcard ? für den unbekannten Typ. Auch Wildcards können nach oben und unten beschränkt werden.

public void printCollection( Collection<?> c) { Iterator i = c.iterator();

for (k = 0; k < c.size(); k++) { System.out.println(i.next());

} }

Nachteil dabei ist, das nun in der Methode keine Elemente mehr hinzugefügt werden können, da der richtige Typ ja nun nicht mehr bekannt ist. Genauer:

Methoden, die ein T als Parameter erwarten sind verboten. Methoden, die den generischen Typ T zurückgeben, liefern nun ein Object (bzw. die Schranke).

siehe dazu auch

http://java.sun.com/docs/books/tutorial/extra/generics/wildcards.html

Generics(6)

Referenzen

ÄHNLICHE DOKUMENTE

Variablen, Ausdrücke, Kontrollstrukturen Klassen, Kapselung, Interfaces, Vererbung. überschreiben vs überladen

Ein Hinweis darauf, dass die in den Meniskusersatz eingewanderten Zellen nicht nur Kollagenfasern gebildet hat- ten, sondern diese sich unter dem funk- tionellen Stress parallel

Auf die Einhaltung der Arbeitsplatzgrenzwerte und sonstiger Grenzwerte achten. 7.1.3 Weitere Angaben zur Handhabung.. Keine weiteren Angaben. 7.1.4 Hinweise zum Brand-

Wenn Sie bei einem oder mehreren Unter- nehmen der ERGO Gruppe versichert sind, können Ihre Daten also durch ein Unternehmen der ERGO Gruppe verarbeitet werden. Beispielsweise aus

Aus informationsstruktureller Sicht lässt sich der französische Aussagesatz mit Rechtsversetzung mit dem deutschen Aussagesatz, dessen Vorfeld durch das PH-es

Orientierende Untersuchungen von Grünkohl im näheren Umfeld des Hafengebietes in den KGA Hafenwiese, Westerholt und Hobertsburg führen zu deutlich erhöhten Gehalten von PCB in

In der Location, Raumbezeichnung, Straße, PLZ und Ort werden Name1 und Name2 der Name Klinik die medizinischen Geräte und den Ablauf auf

Adressat männlich Herr %firstname% %lastname%. Adressat weiblich Frau