Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 1 Generisches Programmieren.

Ähnliche Präsentationen


Präsentation zum Thema: "PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 1 Generisches Programmieren."—  Präsentation transkript:

1 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 1 Generisches Programmieren

2 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 2 Generisches Programmieren Generisches Programmieren dient der Wiederverwendbarkeit von Programmcode Generische Datenstrukturen können eine Vielzahl von eigentlich verschiedenartigen Datentypen repräsentieren Generische Methoden parametrisieren einen abstrakten Vor- gang, derart dass er nur ein einziges Mal programmiert werden muss und trotzdem in vielen Fällen anwendbar ist Gemeinsamkeit von Datenstrukturen und Methoden werden auf einer hohen Abstraktionsebene herausgearbeitet Generisches Programmieren in Java kann unter der Verwendung der Klasse Objekt oder durch generische Klassen bewerkstelligt

3 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 3 Generisches Programmieren mit der Wurzelklasse Objekt

4 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 4 Die Wurzelklasse Object Methoden der Klasse Object werden von allen Objekten geerbt clone(), equals(), finalize(), getClass(), hashCode(), toString(), notify(), notifyAll(), sowie mehrere Versionen von wait(). Methoden in Object sind “Basismethoden”, die in abgeleiteten Klassen sinnvoll überschrieben werden sollten toString() konvertiert ein beliebiges Objekt in eine Zeichenkette MyObj myObject = newMyObj(); Answer theAnswer = new Answer(); System.out.println(myObject); String s = ´´The answer is: ´´ + theAnswer;

5 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 5 Objektgleichheit Methode equals() bestimmt, ob zwei Objekte gleich sind Gleichheit zweier Zeichenketten String userName = ´´Joe´´... if ( userName.equals(suspectName) ) arrest(userName); Voreinstellung!!! Methode equals() vergleicht Referenzen Achtung!!!! Überladen anstelle von Überschreiben der Methode kann zu Fehlern führen public boolean equals(Point arg) {... } // Falsch !!! public boolean equals(Object arg) {... }// Richtig !!!

6 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 6 Flaches Kopieren versus Tiefes Kopieren Methode clone() erzeugt eine identische Kopie eines Objektes flaches Kopieren Kopieren mit clone() ist nur dann zulässig, wenn die betreffende Klasse das Interface Cloneable implementiert Interface nicht implementiert => CloneNotSupportedException Achtung!! Methode clone() ist in Object als protected deklariert Kopieren von Objekten Flaches Kopieren Tiefes Kopieren Objekt 1 Objekt 2 Objekt 1´ Objekt 1´ Objekt 2

7 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 7 Beispiel: Öffentliche Kopiermethode public class Buffer implements Cloneable { int [] buffer = new int[100];... public Object clone() { Object theClone = null; try{ theClone = super.clone(); } catch(CloneNotSupportedException e) { } return theClone; }

8 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 8 Klassen der Standardtypen für jeden Standardtyp gibt es in Java eine Wrapperklasse Character, Short, Integer, Long, Boolean, Float und Double Transformation in ein Objekt int i = 1903; Integer intObj = new Integer(i); myVector.addElement(intObj); Konvertierung in einen String float f = 1.234f; String s = Float.toString(f); Konvertierung in einen anderen numerischen Datentyp Double aDouble = new Double(53.23E6); long l = aDouble.longValue();

9 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 9 Autoboxing: Boxing und Unboxing primitive Datentypen und Wrapperklassen werden seit Version 5.0 bei Bedarf ineinander umgewandelt int i = 4711; Integer j = i;// steht für j = Integer.valueOf(i); int k = j; // steht für j = j.intValue(); Boxing nennt man die automatische Erstellung eines Wrapper-Objekts Unboxing steht für die Entnahme des primitiven Wert eines Wrapper- Objekts (mit einer passenden xxxValue()-Methode) Unboxing wird nur dann geführt, wenn ein Ausdruck einen primitiven Wert erwartet Integer i1 = new Integer(1); Integer i2 = new Integer(1); System.out.println(i1 >= i2);//true System.out.println(i1 <= i2);//true System.out.println(i1 == i2);//false

10 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 10 Generische Datenstrukturen in Java ist jede Klasse automatisch eine Unterklasse der Klasse Objekt allgemeinverwendbare Datentypen wie Listen, Stapel, etc. können in Java mit Elementen vom Typ Objekt definiert werden Datentypen, die über Elemente von der Klasse Objekt definiert sind, heißen generisch bzgl. der Elementtypen Paket java.util enthält eine Reihe generischer Datentypen Klasse Stack repräsentiert einen generischen Stapel Klasse Vector repräsentiert eine generische erweiterbare Reihung

11 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 11 Beispiel: Liste als generische Datenstruktur public class Node{ Object data; // Datenelement Node next;// Zeiger auf nächste Listenzelle } public class List{ private Node head;// Kopf der Liste... }

12 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 12 Generische Methoden Generische Methoden arbeiten auf allen Spezialisierungen des generischen Typs, müssen aber evtl. zur Laufzeit oder Übersetzungszeit spezialisiert werden public class List{ private Node head;// Kopf der Liste... void scan(){ for(Node cursor = head; cursor != null; cursor =cursor.next){ // Aktion zur Zeit leer }

13 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 13 Beispiel: Längenbestimmung public class List{ private Node head;// Kopf der Liste... int length(){ int length = 0; for(Node cursor = head; cursor != null; cursor =cursor.next){ length++; } return length; }

14 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 14 Beispiel: Elemente ausdrucken public class List{ private Node head;// Kopf der Liste... void print(){ for(Node cursor = head; cursor != null; cursor =cursor.next){ System.out.println(cursor.data.toString()); }

15 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 15 Generische Programmierung mit generischen Klassen

16 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 16 Generische Programmierung in der Vergangenheit ausschließlich unter Verwendung der Wurzelklasse Objekt Generics wurden mit der Version 1.5 zur generischen Programmierung in Java eingeführt Schablonen zur Klassen-, Schnittstellen- oder Methodenbeschreibung in denen verwendete Typen durch Typvariablen darstellt werden können unterstützen ein statisch typsicheres generisches Programmieren jedoch können nur generische Typen über Referenztypen und nicht über primitive Datentypen definiert werden generische Klassen und Methoden werden vom Compiler in Datenstrukturen übersetzt, die auf der Klasse Objekt basieren

17 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 17 Beispiel: Generisches Programmieren (bisher) class Node{ private Node left, private Node right; private Object info; Node(Object i, Node l, Node r) {info = i, right = r; left = l;} Node(Object i) {this(i, null, null);} Object getInfo(){return info;} void setInfo(Object i){info = i;} Node getLeft(){return left;} void setLeft(Node l){left = l;} Node getRight(){return right;} void setRight(Node r){right = r;} }

18 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 18 Probleme: Generische Programmierung (bisher) in mit Node aufgebauten Bäumen können Knoteninformationen von verschiedenartigen Datentypen sein Node n1 = new Node(´´foo´´); Node n2 = new Node(3.141592); Node n3 = new Node(23, n1, n2); zum Auslesen von Knoteninformation ist eine nicht sichere Typkonvertierung notwendig String s = (String) n.getInfo();

19 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 19 Generische Klassen und Typen eine generische Klasse ist eine Klassendefinition, in der unbekannte Typen durch Typvariablen beschrieben werden ein generischer Typ ist die Instanzierung einer generischen Klasse mit einem konkreten Typargument Definition einer generischen Klasse class name {….} class name {….} Definition und Verwendung eines generischen Typs name d;

20 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 20 Beispiel: Generische Klasse Node class Node { private Node left, private Node right; private T info; Node(T i, Node l, Node r) {info = i, right = r; left = l;} Node(T i) {this(i, null, null);} T getInfo(){return info;} void setInfo(T i){info = i;} Node getLeft(){return left;} void setLeft(Node l){left = l;} Node getRight(){return right;}void setRight(Node r){right = r;} }

21 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 21 Beispiel: Generische Typen Node ns; ns = new Node (´´foo´´); Node ni; ni = new Node (1); Node ni; ni = new Node (´´foo´´);// Typfehler Node ni = new Node (1); Node ns = new Node (´´foo´´, ni, null); // Typfehler; String s = ns.getInfo(); // ohne Typcast Node = ns.getLeft();

22 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 22 Beispiel: Mehrere Typvariablen class Pair { private final T first; private final U second; Pair( T fst, U snd){ first = fst; second = snd; } T getFirst() { return first;} U getSecond(){ return second;} } Pair psi = new Pair (´´foo´´,1);

23 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 23 Generische Schnittstellen interface Taggable { void setTag(T tag); T getTag(); } class Someclass implements Taggable { private String tag; public void setTag(String t) {tag = t;} public String getTag() { return tag;} } class Node implements Taggable { private T tag; public void setTag(T t) {tag = t;} public T getTag() { return tag;} }

24 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 24 Typeinschränkung in generischen Klassenbeschreibungen kann die Zulässigkeit von Typargumenten durch extends und super eingeschränkt werden class Node {…} Typargumente in generischen Typen müssen zu etwaigen Typeinschränkungen kompatibel sein Node ni; //ok Node nd; //ok Node no; //Fehler! Node ns; // Fehler! Typvariablen können auch mehrere Typeinschränkungen haben Class classname

25 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 25 Beispiel: Mehrfache Typeinschränkung interface Timestamped{ String getTimestamp(); } interface Printable{ void print(); } class Node { … } class InfoDeluxe implements Timestamped, Printable{ String getTimestamp(){ … } void print(){ … } } Node nidlx; //okNode ns; //Fehler

26 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 26 Beispiel: Typeinschränkungen mit Typvariablen geordnete Bäume: class Node > { … } Node ns;//ok Node ni;//ok Node no;//Fehler eine Klasse, deren Oberklasse Comparable implementiert, wird nicht akzeptiert class Base implements Comparable { … } class Derived extends Base {... } Node nb; //ok Node nd; // Fehler

27 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 27 Generische Typen - Wildcardtypen Vererbungsbeziehung zwischen Typargumenten überträgt sich nicht auf generische Typen Node = new Node (23); //Fehler anstelle eines Typarguments kann ´´?´´ in Wildcardtypen eingesetzt werden alle generischen Typen der gleichen generischen Klassen sind kompatibel zum Wildcardtyp der Klasse Node n; n = new Node (23); //ok n = new Node (´´foo´´); //ok Aber: keine Vererbungsbeziehung

28 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 28 Wildcardtypen: Lese- und Schreibzugriffe in der Regel kein lesender und schreibender Zugriff auf Wildcardtypen Node n = Node (23); String s = n.getInfo(); //Fehler Integer i = n.getInfo(); //Fehler n.setInfo(1);//Fehler mit Ausnahme zweier Grenzfälle Object x = n.getInfo(); //ok n.setInfo(null); //ok

29 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 29 Wildcardtypen: Verwendung Wildcardtypen eignen sich für Situationen in denen das konkrete Typargument keine Rolle spielt class Util{ int nodesCount(Nodes n){ if(n == null) return 0; else return 1 + nodesCount(n.getLeft()) + nodesCount(n.getRight()); }

30 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 30 Wildcardtypen: Upper Bounds Einschränkung der Kompatibilität von Wildcardtypen mit dem Schlüsselwort extends Node n; kompatibel sind alle Typen, deren Typargument Number oder eine Unterklasse von Number ist n = new (23);//ok n = new (new Objekt());//Fehler kein schreibender Zugriff (ausser null-Referenzen) aber lesender Zugriff (liefert im Beispiel immer eine Unterklasse von Number)

31 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 31 Wildcardtypen: Lower Bounds Komplementäres Einschränken von Wildcardtypen mit dem Schlüsselwort super Node n; kompatibel sind alle Typen, deren Typargument Number oder eine Oberklasse von Number ist n = new (23);//Fehler n = new (new Objekt());//ok kein lesender Zugriff (ausser Objekt-Referenzen) aber schreibender Zugriff (liefert im Beispiel immer ein Argument vom Typ Number)

32 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 32 Generische Typen - Übersicht ArtLesenSchreibenkompatible Typargumente C erlaubt T C verboten alle C erlaubtverbotenB und Unterklassen C verbotenerlaubtB und Oberklassen

33 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 33 Generische Klassen – Behandlung durch Compiler generische Klassen werden unter Verwendung der Wurzelklasse Objekt in normale nicht-generische Klassen überführt Typvariablen und -einschränkungen werden aufgezeichnet und später in Form von Signaturbeschreibungen in den Bytecode eingefügt Typvariablen in spitzen Klammern werden gelöscht Typvariablen mit Typeinschränkungen werden durch die zuerst genannte Einschränkung ersetzt Typvariablen ohne Typeinschränkung werden durch Objekt ersetzt alle generischen Typen teilen sich eine einzige Implementierung ihrer Klasse

34 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 34 Beispiel: Übersetzung der Klasse Node class Node{ private Node left, private Node right; private Object info; Node(Object i, Node l, Node r) {info = i, right = r; left = l;} Node(Object i) {this(i, null, null);} Object getInfo(){return info;} void setInfo(Object i){info = i;} Node getLeft(){return left;} void setLeft(Node l){left = l;} Node getRight(){return right;} void setRight(Node r){right = r;} }

35 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 35 Generische Typen - Behandlung durch Compiler nach Überprüfung der korrekten Verwendung generischer Typen wird nicht-generischer Quellcode erzeugt, dabei werden Typargumente, einschließlich Wildcards, in spitzen Klammern gelöscht Typkonvertierungsoperationen eingeschoben, wo ein Wert eines Typarguments benutzt wird Generisches Programm: Node n = new Node (´´foo´´); String s = n.getInfo(); Erzeugtes nicht-generisches Programm: Node n = new Node(´´foo´´); String s = (String) n.getInfo();

36 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 36 Generische Typen - Rawtypes bei der Übersetzung von generischen Klassen entstehen sogenannte Rawtypes Rawtypes sind normale nicht-generische Klassen und lassen sich auch als solche benutzen Node n = new Node(´´foo´´); String s = (String) n.getInfo(); die korrekte Nutzung von Rawtypes unterliegt dem Programmierer der Compiler übersetzt zwar den Code, warnt aber gleichzeitig bei der Nutzung von Rawtypes uses unchecked or unsafe operations

37 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 37 Generische Typen - Grenzen keine Typvariablen in statischen Definitionen class Broken { static T data; // wird nicht übersetzt } keine dynamische Typprüfung von Typvariablen class Node { boolean hasMatchingType(Object x){ if(x instanceof T){// wird nicht übersetzt … }

38 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 38 Generische Typen - Grenzen wirkungslose Typkonvertierungen auf Typvariablen class Node { private T info; void setAny(Object x){info = (T) x;} // Warnung: unchecked cast to Type T } obwohl nur Warnungen vom Compiler gemeldet werden, können dynamische Laufzeitfehler die Folge sein Node ns = new Node (´´foo´´); ns.setAny(23); String s = ns.getInfo();// ClassCastException

39 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 39 Generische Typen - Grenzen keine Reihungen und Konstruktoraufrufe von Typvariablen class Node { private T info; private T[]a = new T[100]; // wird nicht übersetzt Node(){info = new T();} // wird nicht übersetzt } Erzeugung von Reihungen ist jedoch indirekt möglich class Node { private T[]a = (T[]) new Object[100]; // Warnung void set(int i, T t){a[i] = t;} T get(int i){return a[i];} } Typvariablen können keine Oberklassen bilden

40 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 40 Polymorphe Methoden Polymorphe (generische) Methoden sind ebenfalls Sprachmittel ab Java 1.5 Verwendung ist nicht auf generische Klassen beschränkt, sondern kann auch in gewöhnlichen Klassen erfolgen Deklaration [modifiers] rtype name([formPars]){...} Aufruf Reference. name([actPars]); wobei Reference für eine explizite Objekt- bzw. Klassenreferenz steht (ggf. ist auch this zu verwenden).

41 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 41 Beispiel: Polymorphe Instanzmethoden T vote(T x, T y, T z){ if(x.equals(y)) return x; if(y.equals(z)) return y; if(z.equals(x)) return z; return null; } String s = this. vote(“foo”,“bar”,“foo”); int i = this. vote(1,2,2);

42 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 42 Beispiel: Polymorphe Klassenmethoden class Util{ T[] makeArray(T… a){ return a; } String [] s = Util. makeArray(“1st”,“2nd”,“3rd”); Integer[] i = Util. vote(1,2,3);

43 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 43 Polymorphe Methoden: Typinferenz Typinferenz erlaubt das Weglassen von Typargumenten beim Aufruf polymorpher Methoden String s = vote(“foo”,“bar”,“foo”); int i = vote(1,2,2); beim Aufruf mit Argumenten unterschiedlichen Typs für die gleiche Typvariable wählt man die speziellste Unterklasse Number n = vote(1,3.14,2); // Ok Integer i = vote(1,3.14,2); // Fehler Double n = vote(1,3.14,2); // Fehler Object n = vote(1,3.14,2); // Ok wegen Kompatibilität

44 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 44 Polymorphe Methoden: Typeinschränkung wie bei generischen Typen können die Typargumente von polymorphen Methode einer Typeinschränkungen unterliegen > T median(T x, T y, T z){ …. } int i = median(1,3,2); // Ok Objec c = this. median(..); // Fehler

45 PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 45 Polymorphe Methoden: Überladen Polymorphe Methoden dürfen nur überladen werden, wenn durch Übersetzung kein Konflikt zu anderen Methoden entsteht Object vote(Object x, Object y, Object z){..} T vote(T x, T y, T z){..} // nicht verträglich T vote(T x, T y, T z){..} // verträglich beim Überladen werden polymorphe Methoden erst dann berücksichtigt, wenn keine normalen Methoden passen void foo(T x){} //Passt nur wenn x keine Number ist void foo(Integer x){} void foo(Number x){}


Herunterladen ppt "PD Dr. habil. Wolfram Amme, Generisches Programmieren, Programmierpraktikum, FSU Jena, WS 2006/07 1 Generisches Programmieren."

Ähnliche Präsentationen


Google-Anzeigen