C O L mputational gic Programmiermethodik René Thiemann Institute of Computer Science University of Innsbruck SS 2013 RT (ICS @ UIBK) Programmiermethodik 1/613 Übersicht Einführung Einführung in Java Objektorientierung Vererbung und Polymorphismus Ausnahmebehandlung Pakete und Dokumentation Generische Programmierung Java Collection Framework Unit Tests Entwurfsmuster GUI-Programmierung in Java Ausblick RT (ICS @ UIBK) Programmiermethodik 2/613 Einführung Übersicht Einführung Organisation Motivation Kursinhalt RT (ICS @ UIBK) Programmiermethodik 3/613 Einführung Organisation Übersicht Einführung Organisation Motivation Kursinhalt RT (ICS @ UIBK) Programmiermethodik 4/613 Einführung Organisation Organisation LVA 703016 VO 3 cl-informatik.uibk.ac.at/teaching/ss13/pm/ VO PS Donnerstags Montags Montags Montags Montags 11:15 – 13:45 12:15 – 13:45 14:15 – 15:45 16:15 – 17:45 12:15 – 13:45 HS D RR 15 RR 15 RR 15 HSB 5 (RT) (CH) (CH) (PZ) (BH) online Registrierung für PS – erforderlich bis zum 1. 3. 2013 online Registrierung für VO – erforderlich bis zum 31. 3. 2013 Sprechstunden Christian Haisjackl C125 Mittwochs 09:00 – 11:00 Benedikt Hupfauf nach Vereinbarung René Thiemann 3M09 Montags 13:00 – 15:00 Philipp Zech 3M02 Montags 14:00 – 16:00 RT (ICS @ UIBK) Programmiermethodik 5/613 Einführung Organisation Literatur • Hanspeter Mössenböck Sprechen Sie Java? dpunkt.verlag (in Bücherei) • David J. Barnes, Michael Kölling Java lernen mit BlueJ – Eine Einführung in die objektorientiere Programmierung Pearson Studium (in Bücherei) • Bernhard Lahres, Gregor Rayman Objektorientierte Programmierung – Das umfassende Handbuch Galileo Computing (frei herunterladbar) RT (ICS @ UIBK) Programmiermethodik 6/613 Einführung Organisation Weitere Quellenangaben • Stefan Podlipnig Programmiermethodik Foliensatz zur Vorlesung im SS 2012 RT (ICS @ UIBK) Programmiermethodik 7/613 Einführung Organisation Organisation – Vorlesung • Vorlesungsfolien werden auf der Homepage vor der jeweiligen Vorlesung online gestellt ⇒ Folien zur Vorlesung mitbringen, um darin Notizen zu machen • Prüfung: schriftlich, am letzen Vorlesungstermin: 27. Juni RT (ICS @ UIBK) Programmiermethodik 8/613 Einführung Organisation Organisation – Proseminar • Wöchentliche Aufgabenblätter (Gruppenarbeit) • Im Proseminar wird Blatt letzter Woche besprochen und neues Blatt vorgestellt • Abgabe der Lösungen inklusive Sourcecode etc. per E-Mail an jeweiligen Lehrveranstaltungsleiter (mit Betreff: [PM13]) • Test während des Semesters (3. Juni) • Benotung: Wöchentliche Übungsblätter (50%) und Test (50%) • Mindestens 60% der Übungsaufgaben müssen gelöst werden! • Anwesenheitspflicht RT (ICS @ UIBK) Programmiermethodik 9/613 Einführung Motivation Übersicht Einführung Organisation Motivation Kursinhalt RT (ICS @ UIBK) Programmiermethodik 10/613 Einführung Motivation Ziel der Vorlesung • Grundlagen der Programmierung (aus der Einführung in die Programmierung) vertiefen • Grundkonzepte der Objektorientierung verstehen und anwenden • Analyse • Design • Implementierung • Erlernen einer modernen objektorientierten Programmiersprache • Verstehen moderner Programmierprinzipien • Methodisches Programmieren vertiefen RT (ICS @ UIBK) Programmiermethodik 11/613 Einführung Motivation Eigenschaften einer guten Software • korrekt – Aufgaben so erfüllen, wie es erwartet wird (Vorlesungen über Programmverifikation und Logik) • effizient – wenig Ressourcenverbrauch, schnelle Antworten (Vorlesung Algorithmen und Datenstrukturen) • wartbar – leicht erweiterbar und änderbar (diese Vorlesung) • benutzerfreundlich – intuitiv bedienbar RT (ICS @ UIBK) Programmiermethodik 12/613 Einführung Motivation Modularisierung in der Technik • Modularisierung in der Technik ist notwendig, um komplexe Dinge herzustellen • Beispiel LKW • Grober Entwurf: Motor, Karosserie, Reifen, Sitze, . . . • Motor: Kolben, Zündkerzen, Zylinder, . . . Zündkerze • Zündkerze: Isolierung, Elektrode, . . . • ... • Reifen: Gummimischung, Drahtgeflecht, Profil, . . . • ... • Wichtig: für jedes Modul braucht man nur Verständnis der Funktionalität, nicht aber Detailkenntnis wie es diese erreicht! RT (ICS @ UIBK) Programmiermethodik 13/613 Einführung Motivation Modularisierung in der Software(-Technik) • Modularisierung in der Software-Entwicklung ist wesentlich, um komplexe Software zu erstellen • Beispiel Textverarbeitung • Grober Entwurf: Layout, Rechtschreibprüfung, Silbentrennung, GUI, . . . • Layout: Dimensionsberechnung, Blocksatz, Schusterjungen, . . . • GUI: . . . • ... • Wichtig: für jedes Modul braucht man nur Verständnis der Funktionalität, nicht aber Detailkenntnis wie es diese erreicht! RT (ICS @ UIBK) Programmiermethodik 14/613 Einführung Motivation Objektorientierung Objektorientierung . . . • . . . bietet eine Möglichkeit, modulare Software zu entwickeln • . . . basiert auf den folgenden drei Konzepten: • Datenkapselung • Polymorphie • Vererbung RT (ICS @ UIBK) Programmiermethodik 15/613 Einführung Motivation Datenkapselung • Motto: “ich muss nicht alles aufschrauben, bevor ich es benutze” • in der Technik: • für den Austauch einer Glühbirne ist deren Aufbau unwichtig • man muss nur auf die passende Fassung und Leistung achten • in der Software: • für die Nutzung einer Datenbank ist dessen interne Struktur irrelevant • wichtig ist jedoch die Kenntnis der Funktionalität (speichere Daten, frage Daten ab, . . . ) • die Kapselung verhindert zudem (unbeabsichtigte) Manipulation, indem man etwa interne Daten ändert und somit inkonsistenten Status herbeiführt RT (ICS @ UIBK) Programmiermethodik 16/613 Einführung Motivation Polymorphismus • Idee: Einfache Austauschbarkeit durch standardisierte Schnittstelle • in der Technik: RT (ICS @ UIBK) Programmiermethodik 17/613 Einführung Motivation Polymorphismus • Idee: Einfache Austauschbarkeit durch standardisierte Schnittstelle • in der Technik: kompatibel zu vielen Lampen! RT (ICS @ UIBK) Programmiermethodik 17/613 Einführung Motivation Polymorphismus • Idee: Einfache Austauschbarkeit durch standardisierte Schnittstelle • in der Technik: kompatibel zu vielen Lampen! • in der Software: • biete Service für unterschiedliche Benutzer • Dokumentation in HTML statt .docx ⇒ freie Wahl des Betriebssystem und eines Browsers • Austausch von Teilprogrammen • besseres Sortierverfahren (welches Methode “sort” biete) • alternativer Fenstermanager (mit Methoden “createWindow”, . . . ) • kostengünstigere Datenbank (welche auf SQL-Standard basiert) RT (ICS @ UIBK) Programmiermethodik 17/613 Einführung Motivation Vererbung • Motto: “das Rad nicht neu erfinden” • Idee: erweitere oder verändere bestehende Funktionalität • in der Technik: • um LKW mit Kran zu entwickeln, modifiziert man normalen LKW ⇒ Vorteil: alte Funktionalität braucht nicht neu erfunden werden • weitere Beispiele: Häuserbau, A-Team, . . . • in der Software: • erstelle Basisfunktionalität . . . • . . . die auf verschiedenste Weisen erweitert oder modifiziert werden kann • Beispiel: Java Collections Framework RT (ICS @ UIBK) Programmiermethodik 18/613 Einführung Kursinhalt Übersicht Einführung Organisation Motivation Kursinhalt RT (ICS @ UIBK) Programmiermethodik 19/613 Einführung Kursinhalt Java • um Objektorientierung zu verstehen, benötigen wir objektorientierte Programmiersprache: C++, C#, Java, OCaml, Smalltalk, . . . http://www.oracle.com/technetwork/java/index.html • Grundkenntnisse der Programmierung in einer imperativen Sprache wie C oder Pascal werden vorausgesetzt! • für leichten Einstieg in Java wird IDE BlueJ empfohlen: http://www.bluej.org • für komplexere Projekte wird IDE Eclipse genutzt: http://www.eclipse.org RT (ICS @ UIBK) Programmiermethodik 20/613 Einführung Kursinhalt Inhalt • Einführung in Java • Grundlagen der Objektorientierung (Objekte, Klassen) • Vererbung und Polymorphismus • Generische Programmierung • Ausnahme-Behandlung • Java Collections Framework • Entwurfsmuster • GUI-Programmierung • ... RT (ICS @ UIBK) Programmiermethodik 21/613 Einführung in Java Übersicht Einführung in Java Historie und Features Grundlegende Elemente eines Java Programms (ohne OO) Datentypen Ausdrücke Anweisungen Arrays Methoden RT (ICS @ UIBK) Programmiermethodik 22/613 Einführung in Java Historie und Features Übersicht Einführung in Java Historie und Features Grundlegende Elemente eines Java Programms (ohne OO) RT (ICS @ UIBK) Programmiermethodik 23/613 Einführung in Java Historie und Features Historie • Start 1991 • Sun Microsystems (seit 2010 Tochterunternehmen von Oracle) • Angelehnt an C++, Elemente aus Smalltalk (Bytecode, Garbage Collection) • Ziel: Entwicklung einer Hochsprache für hybride Systeme im Consumer-Electronic Bereich • Sun Demo Web-Browser HotJava in den 90-ern (Applets) • Durchbruch 1995 • Netscape Navigator 2.0 mit integrierter Java Virtual Machine • Mittlerweile verschiedene Versionen • Java 7 Standard Edition (diese Vorlesung) • Java 6 Enterprise Edition (Business-Applikationen etc.) • Java Micro Edition (Handy, PDA, . . . ) • Java Card Edition (Smartcards) RT (ICS @ UIBK) Programmiermethodik 24/613 Einführung in Java Historie und Features Java ist . . . • Objektorientiert • Portierbar • Robust • Strenges Typsystem • Behandlung von Ausnahmen (Exception Handling) • Automatische Speicherbereinigung (Garbage Collection) • Nebenläufig • Sicher RT (ICS @ UIBK) Programmiermethodik 25/613 Einführung in Java Historie und Features Java ist objektorientiert • Objektorientierung ist ein Programmierparadigma • Programmierparadigma = Sichtweise auf und Umgang mit zu verarbeitenden Daten und Operationen • Beispiele von Programmierparadigmen • Imperatives Programmierparadigma (LV Einführung in die Programmierung) sequenziell Abarbeitung einer Folge von Anweisungen • Objektorientiertes Programmierparadigma (diese LV, Java) weitergehende Konzepte wie Klassen, Vererbung und Polymorphie • Funktionales Programmierparadigma (LV Funktionale Programmierung) funktionale Programme kennen keine Wertzuweisung; Definition von Funktionen, die Eingabe in Ausgabe transformiert • Logisches Programmierparadigma (LV Logikprogrammierung) Programm ist Menge von Schlussfolgerungen; Interpreter beantwortet, welche Schlüsse gezogen werden können RT (ICS @ UIBK) Programmiermethodik 26/613 Einführung in Java Historie und Features Beispiel: Konkatenation von Listen A und B • Imperativ: • Aktuelles Element E = Kopf von A • Solange Nachfolger von E existiert, E = Nachfolger von E • Setze Nachfolger von E auf Kopf von B RT (ICS @ UIBK) Programmiermethodik 27/613 Einführung in Java Historie und Features Beispiel: Konkatenation von Listen A und B Lösung berücksichtigt nicht Spezialfall A = [ ] • Imperativ: • Aktuelles Element E = Kopf von A • Solange Nachfolger von E existiert, E = Nachfolger von E • Setze Nachfolger von E auf Kopf von B RT (ICS @ UIBK) Programmiermethodik 27/613 Einführung in Java Historie und Features Beispiel: Konkatenation von Listen A und B Lösung berücksichtigt nicht Spezialfall A = [ ] • Imperativ: • Aktuelles Element E = Kopf von A • Solange Nachfolger von E existiert, E = Nachfolger von E • Setze Nachfolger von E auf Kopf von B • Objektorientiert: • intern: wie imperative Lösung • Aufruf: A.append(B) (verändert A) RT (ICS @ UIBK) Programmiermethodik 27/613 Einführung in Java Historie und Features Beispiel: Konkatenation von Listen A und B Lösung berücksichtigt nicht Spezialfall A = [ ] • Imperativ: • Aktuelles Element E = Kopf von A • Solange Nachfolger von E existiert, E = Nachfolger von E • Setze Nachfolger von E auf Kopf von B • Objektorientiert: • intern: wie imperative Lösung • Aufruf: A.append(B) (verändert A) • Funktional: • append([ ], B) = B • append([X | A], B) = [X | append(A, B)] • Aufruf append([1,2], [4,5]) liefert [1,2,4,5] RT (ICS @ UIBK) Programmiermethodik 27/613 Einführung in Java Historie und Features Beispiel: Konkatenation von Listen A und B Lösung berücksichtigt nicht Spezialfall A = [ ] • Imperativ: • Aktuelles Element E = Kopf von A • Solange Nachfolger von E existiert, E = Nachfolger von E • Setze Nachfolger von E auf Kopf von B • Objektorientiert: • intern: wie imperative Lösung • Aufruf: A.append(B) (verändert A) • Funktional: • append([ ], B) = B • append([X | A], B) = [X | append(A, B)] • Aufruf append([1,2], [4,5]) liefert [1,2,4,5] • Logisch: • append(A, B, C) ist wahr, gdw. C Konkatenation von A und B ist • append([ ], B, B). • append([X | A], B, [X | C]) ← append(A, B, C). • Aufruf append([1,2], [4,5], Xs) liefert Antwort Xs = [1,2,4,5] • Aufruf append(A, B, [1,2,3]) liefert Antworten A = [ ], B = [1,2,3] oder A = [1], B = [2,3] oder A = [1,2], B = [3] oder A = [1,2,3], B = [] RT (ICS @ UIBK) Programmiermethodik 27/613 Einführung in Java Historie und Features Java ist portierbar • Portierbarkeit leitet sich aus Ausführungsschema ab • Ausführungsschema bestimmt wie Programm ausgeführt wird • Kompiliert • • • • Programm wird in Zielsprache (Maschinencode) übersetzt Hohe Ausführungsgeschwindigkeit Überprüfung auf Fehler vor Ausführung Übersetzung in Maschinencode macht Programm Plattform abhängig • Interpretiert • Programm wird zur Laufzeit eingelesen und Befehl für Befehl abgearbeitet • Langsamere Ausführungsgeschwindigkeit • Tests und kleinere Änderung komfortabel durchführbar • Programme laufen auf jeder Plattform, für die Interpreter vorhanden ist • Java nutzt Mischform • Programm wird in Zwischencode übersetzt (Bytecode) • Bytecode wird mittels Interpreter ausgeführt (virtuelle Maschine, JVM) • JVM dient als Schnittschnelle zwischen Bytecode und Betriebssystem RT (ICS @ UIBK) Programmiermethodik 28/613 Einführung in Java Historie und Features Java Bytecode • Plattformunabhängig und kompakt • Interpreter für Bytecode ist kleiner und schneller als Interpreter für ursprünglichen Source-Code • Endbenutzer hat keinen Zugriff auf den Source-Code • Vorteil: kommerzielle Verwendung (Source ist Betriebsgeheimnis) • Nachteil: eigene Modifikationen kaum möglich (Kunde darf gekauftes Produkt nicht anpassen) • Interpreter kann zusätzliche Überprüfungen / Einschränkungen für Sicherheit durchführen (kein Festplattenzugriff für Java-Applets) RT (ICS @ UIBK) Programmiermethodik 29/613 Einführung in Java Historie und Features Java ist robust: Strenges Typsystem • strenges Typsystem: • Variablen haben festen Typ • Funktionen können nur mit kompatiblen Parameter aufgerufen werden • Fehlerhafte Ausdrücke / Typfehler werden nicht akzeptiert • ohne Typsystem: • Variablen können beliebige Werte zugewiesen werden • Funktionen interpretieren Eingaben, als hätten sie passenden Typ • Beispiel: Interpretation von Trennzeichen / Strings als Zahlen expr 1000 + 3 1_000 + 3 ”1000” + 3 ”1_000” + 3 1,000,000 + 3 1.000.000 + 3 1_000_000 + 3 RT (ICS @ UIBK) Java: int x = expr 1003 1003 Fehler Fehler Fehler Fehler 1000003 Programmiermethodik Perl: $x = expr 1003 Fehler erst 1003 zur Laufzeit 1003 sichtbar 4 1 3 1000003 30/613 Einführung in Java Historie und Features Java ist robust: Garbage Collection • ohne Garbarge Collection (z.B. in C) • Programm fordert Speicher an und gibt ihn wieder frei • Fehleranfällig • Speicher zu früh freigeben: Referenzen zeigen ins Nichts • Speicher zu spät (gar nicht) freigeben: hoher (zu hoher) Speicherbedarf • mit Garbarge Collection • Programm fordert Speicher an, Laufzeitsystem kümmert sich um Freigabe • Vorteil: wenig Speicherlecks, keine fehlerhaften Referenzen • Nachteil: Zeitpunkt der Garbage Collection nicht voraussehbar ⇒ schlecht für Echtzeit-Anforderungen RT (ICS @ UIBK) Programmiermethodik 31/613 Einführung in Java Historie und Features Java ist nebenläufig Nebenläufigkeit • führe Teilprogramme auf mehreren Prozessoren auf ⇒ deutlich verbesserte Effizienz auf Multi-Core Rechnern • wird immer wichtiger in Zukunft (Tendenz: gleiche Taktfrequenz, erhöhte Anzahl von Cores) • Vorlesung über Nebenläufige und Parallele Programmierung RT (ICS @ UIBK) Programmiermethodik 32/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Übersicht Einführung in Java Historie und Features Grundlegende Elemente eines Java Programms (ohne OO) Datentypen Ausdrücke Anweisungen Arrays Methoden RT (ICS @ UIBK) Programmiermethodik 33/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Ein einfaches Java-Programm c l a s s MyProgram { s t a t i c v o i d main ( ) { System . o u t . p r i n t ( "Die Fakultaet von 5 ist " ) ; System . o u t . p r i n t l n ( f a c t ( 5 ) ) ; } static int fact ( int n) { int r e s u l t = 1; f o r ( i n t i = 1 ; i <= n ; i ++) result = result ∗ i ; return r e s u l t ; } } RT (ICS @ UIBK) Programmiermethodik 34/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Farbschema • return, for , ... : Schlüsselwörter • ’c’, "hallo", ... : Zeichen und Zeichenketten • fact , MyProgram, ... : frei wählbare Namen • // some comment : Kommentare • 7, <=, ... : der Rest: Operatoren, Zahlen, Klammern, . . . RT (ICS @ UIBK) Programmiermethodik 35/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Struktur eines Java-Programms 1 c l a s s MyProgram { 2 3 s t a t i c v o i d main ( ) { 4 } 5 6 static int fact ( int n) { 7 } 8 9} • Programm hat immer Struktur class SomeName { ... } • Namenskonvention für Klassennamen • mit Großbuchstaben beginnend, danach Kleinbuchstaben • jedes neue Wort wieder mit Großbuchstaben beginnen • Klasse SomeName muss in Datei SomeName.java gespeichert werden (sowohl BlueJ als auch Eclipse machen dies automatisch) • innerer Block (Zeilen 2 - 8) beinhaltet beliebig viele Methoden RT (ICS @ UIBK) Programmiermethodik 36/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Struktur einer Methode (= Unterprogramm) 1 2 3 4 5 6 static int fact ( int n) { int r e s u l t = 1; f o r ( i n t i = 1 ; i <= n ; i ++) result = result ∗ i ; return r e s u l t ; } • Methode hat immer Struktur static returnType methodName (type1 parameterName1, ...) { ... } • Namenskonvention für Methoden- und Parameternamen: wie Klassennamen, nur mit Kleinbuchstaben beginnend • mögliche Rückgabetypen (returnType): • void: nichts wird zurückgegeben Prozedur • int, boolean, String, . . . : etwas wird zurückgegeben Funktion • innerer Block (Zeilen 2 – 5) ist beliebe Sequenz von Anweisungen • in Methoden können lokale Variable deklariert werden ( result und i ) • bei Funktionen muss letzte Anweisung ein return sein RT (ICS @ UIBK) Programmiermethodik 37/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Kommentare • Einzeilig // ... , bis zum Ende der Zeile i n t x = 5 ; // t h i s i s a comment ; x = x + 1 0 ; • Mehrzeilig /∗ ... ∗/ , aber nicht geschachtelt /∗ a m u l t i l i n e comment /∗ i n n e r comments a r e n o t s u p p o r t e d ∗/ may r a n g e o v e r m u l t i p l y l i n e s ∗/ // F e h l e r h a f t e r Kommentar • Dokumentation /∗∗ ... ∗/ : später RT (ICS @ UIBK) Programmiermethodik 38/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Übersicht Einführung in Java Historie und Features Grundlegende Elemente eines Java Programms (ohne OO) Datentypen Ausdrücke Anweisungen Arrays Methoden RT (ICS @ UIBK) Programmiermethodik 39/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Datentypen • Alle Daten haben einen Typ (Datentyp) • Typ schränkt die Benutzung der Daten ein • Wertebereich • Methoden haben Anforderung an Eingabe-Parameter (Bsp: fact ("siebzehn") ist nicht erlaubt) • Java bietet 2 Möglichkeiten • Primitive Datentypen (beginnend mit Kleinbuchstaben) • Datentypdefinition durch Klassen (beginnend mit Großbuchstaben) RT (ICS @ UIBK) Programmiermethodik 40/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Eingebaute Datentypen in Java • Ganze Zahlen (byte (8-bit), short (16-bit), int (32-bit), long (64-bit)) Überlauf beachten: für int x = 2_147_483_647 gilt x + 1 == −2_147_483_648 und x ∗ 2 == −2 • Gleitkommazahlen (float (32-bit), double (64-bit)) Rundungsfehler beachten: es gilt 0.1 + 0.2 != 0.3 und 0.1 + 0.3 == 0.4 und 1e18 + 1 == 1e18 • Logische Werte (boolean, zwei Werte true und false) • Zeichen (char): 16-bit Unicode-Character (’a’, ’\n’, ’ü’, ’\uFFFF’) • Zeichenketten (String): "Hallo!\n", "", "1e18 + 1 == 1e18" • Beachte: String ist kein primitiver Datentyp, sondern Klasse • Vergleich mittels == führt Identitätsvergleich aus (der selbe String?) • Vergleich mittels equals führt Inhaltsvergleich aus (der gleiche String?) S t r i n g x = "ab" , y = "cd" , z = "ab" + "cd" ; boolean b1 = x + y == "abcd" ; // f a l s e boolean b2 = z == "abcd" ; // t r u e boolean b3 = ( x + y ) . e q u a l s ( "abcd" ) ; // t r u e RT (ICS @ UIBK) Programmiermethodik 41/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Deklaration von Variablen • Variablen müssen deklariert werden • Variablen müssen vor erstem Lesezugriff initialisiert werden • Vorteil: Compiler kann passend Speicher allozieren und Fehler erkennen RT s t a t i c v o i d f ( i n t x ) { // P a r a m e t e r x x = x ∗ x + 7; y = x − 2; // F e h l e r , y n i c h t d e k l a r i e r t int y , z , u ; // V a r i a b l e n y , z , und u y = x + 2; z = u + x; // F e h l e r , u n i c h t i n i t i a l i s i e r t i f ( x > y ) { // I n i t i a l i s i e r u n g m i t F a l l u n t e r . u = y; } else { u = 7; } z = u; int a = 3 , b = x , c = a + b ; } (ICS @ UIBK) Programmiermethodik 42/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Namenskonflikte und Sichtbarkeit von Variablen • In jedem Block sind alle äußeren Variablen (und Parameter) sichtbar • Variablennamen müssen so gewählt werden, dass es keine 2 Variablen gibt (bzw. Variable und Parameter), die beide im gleichen Block sichtbar sind und denselben Namen haben s t a t i c void f ( i n t x ) { i n t x ; // F e h l e r , K o n f l i k t m i t P a r a m e t e r x int y ; { int z ; i n t y ; // F e h l e r , 2 V a r i a b l e n y s i c h t b a r { boolean y ; } // g l e i c h e r F e h l e r w i e z u v o r } { String z ; f o r ( i n t y = 1 ; y < 5 ; y++) // F e h l e r wegen y x = x + 5; } } RT (ICS @ UIBK) Programmiermethodik 43/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Übersicht Einführung in Java Historie und Features Grundlegende Elemente eines Java Programms (ohne OO) Datentypen Ausdrücke Anweisungen Arrays Methoden RT (ICS @ UIBK) Programmiermethodik 44/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Wertzuweisung • Ausdrücke werden in z.B. in Wertzuweisungen x = exp; benötigt • Bedeutung: weise der Variable x den Wert des Ausdrucks exp zu • Ausdrücke (Expressions) werden gebildet durch • Literale: true , false , 7 , 3.4 , ’c’ , "hallo" , . . . • Variablen: x , factor , sum , defaultValue , . . . • Operator-Ausdrücke: exp + exp , − exp , exp && exp , exp <= exp , exp ? exp : exp , . . . • Typ-Anpassung: (type) exp • geklammerte Ausdrücke: (exp) • Methodenaufrufe: someMethod(exp,...,exp) , exp.someMethod(exp,...,exp) • Beispiel für komplexeren Ausdruck static int fact ( int x) { r e t u r n ( x <= 1 ? 1 : x ∗ f a c t ( x − 1 ) ) ; } RT (ICS @ UIBK) Programmiermethodik 45/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Präzedenzen und Assoziationen • werden benötigt, um Wert von 100 − 30 − 7 ∗ 2 festzulegen: • Präzedenz regelt Bindungsstärke • ∗ bindet stärker als − ⇒ 100 − 30 − 7 ∗ 2 = 100 − 30 − (7 ∗ 2) = 100 − 30 − 14 • Assoziativität regelt Klammerung bei gleicher Präzedenz • − ist links-assoziativ ⇒ 100 − 30 − 14 = (100 − 30) − 14 = 70 − 14 = 56 RT (ICS @ UIBK) Programmiermethodik 46/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Häufig genutzte Operatoren • Arithmetik: + , − (binär und unär), ∗ , / , % (Rest) • String-Konkatenation: + • Vergleiche: == , != , < , <= , >= , > • logische Operationen: & , && (Konjunktion), | , || (Disjunktion), ! (Negation) • if-then-else: ? : RT (ICS @ UIBK) Programmiermethodik 47/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Typkompatibilität • Operanden, Methoden-Parameter, Zuweisungen benötigen Typkompatibilität • Problematische Beispiele: int x = 2.5 , "vier"+ 5 • Zwei Typen sind kompatibel wenn • sie gleich sind, • sie durch implizite Typanpassung zum gleichen Typ führen • implizite Typanpassung (unidirektional) byte short int long float double String char boolean • Beispiele • int fact (int x) { ... }; ... byte b = 5; int f = fact(b); • byte b = 5; int x = b + 2; double d = x + 2.5; • RT (ICS @ UIBK) String s = "a"+ 3 + 4; s = 3 + 4 + "a"; Programmiermethodik 48/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Explizite Typanpassung • implizite Typanpassung geht nur in eine Richtung • Problematisch • static int foo(int x) { ... } ... long l = 5; int x = foo(l ); • int i = 5; byte x = i + 2; • explizite Typanpassung notwendig, Form: (type) exp • static int foo(int x) { ... } ... long l = 5; int x = foo((int) l ); • int i = 5; byte x = (byte)(i + 2); • explizite Typanpassung kann zu Datenverlusten führen: byte b = (byte) 400; • explizite Typanpassung manchmal trotz impliziter Anpassung nötig: i n t x = 2_000_000_000; long y = x + x ; // −294_967_296 long z = ( long ) x + x ; // 4_000_000_000 RT (ICS @ UIBK) Programmiermethodik 49/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Logische Operationen mit nicht-strikter Auswertung • normale (strikte) Auswertung bei Operatoren & und | • Werte erst Argumente aus, dann berechne Ergebnis • Beispiel: 7 > 5 | 3 ∗ 100 < 2 ∗ 1000 ⇒ true | true ⇒ true • nicht-strikte Auswertung bei Operatoren && und || • Werte zuerst erstes Argument aus, und nur bei Bedarf das zweite • Beispiel: 7 > 5 || 3 ∗ 100 < 2 ∗ 1000 ⇒ true || 3 ∗ 100 < 2 ∗ 1000 ⇒ true • nützlich, um Spezialfälle abzufangen • Beispiel: x != 0 && 5 / x > y • keine Division durch 0 möglich • keine nicht-strikte Auswertungen bei arithmetischen Operationen: • Beispiel: 0 ∗ exp wertet exp aus! RT (ICS @ UIBK) Programmiermethodik 50/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Spezielle Operatoren • Zuweisung = und Abkürzungen += , −= , ∗= , ++ , −− , . . . • x −= y steht abkürzend für x = x − y • x++ steht abkürzend für x += 1 • x++ : x wird nach Verwendung erhöht • ++x : x wird vor Verwendung erhöht • diese Ausdrücke nur als Anweisung verwenden (bessere Lesbarkeit) • Positivbeispiel: x = y = z = 5; x += 7; y−−; • Negativbeispiel: y = 1; y = y++ + ++y + (y += y) + y; • if-then-else Operator ? : • nimmt drei Operanden: booleschen Ausdruck b und e_true, e_false • b ? e_true : e_false wertet zuerst b aus • wenn b == true, dann hat Gesamtausdruck den Wert von e_true • ansonsten ist Ergebnis der Wert von e_false • Beispiel: x < y ? x : y // minimum , x ? true : y // x || y RT (ICS @ UIBK) Programmiermethodik 51/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Übersicht Operatoren Operatoren () , [] , . , postfix ++ und −− Assoz. links 13 präfix ++ und −− , unäres + und − , ~ , ! , (type) rechts 12 11 10 9 8 7 6 5 ∗, /, % binäres + und − << , >> , >>> (bit-shifting) < , <= , >= , > == , != & (logisch und bitweises UND) ^ (logisch und bitweises XOR) | (logisch und bitweises ODER) links links links links links links links links 4 3 && (nicht-striktes UND) || (nicht-striktes ODER) links links Prä. 14 RT 2 ?: 1 = , += , ∗= , /= ,Programmiermethodik %= , |= , &= , ^= , . . . (ICS @ UIBK) rechts rechts 52/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Übersicht Einführung in Java Historie und Features Grundlegende Elemente eines Java Programms (ohne OO) Datentypen Ausdrücke Anweisungen Arrays Methoden RT (ICS @ UIBK) Programmiermethodik 53/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Elementare Anweisungen • Wertzuweisung x = exp; x += exp; ...; x++; • leere Anweisung ; • Variablendeklaration type var1 (= exp1), var2 (= exp2), ...; • Block / Sequenz von Anweisungen (Statements): { s t mt1 ; s t mt2 ; ... } • Rücksprung aus einer Methode • Prozedur: return; • Funktion: return exp; RT (ICS @ UIBK) Programmiermethodik 54/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) If-Anweisungen • Form: if (bexp) s_true else s_false , else-Teil optional • Semantik • Werte booleschen Ausdruck bexp aus • Falls bexp == true, führe s_true aus • Falls bexp == false und else-Fall vorhanden, führe s_false aus • Oft sind s_true und s_false Anweisungsblöcke • If-Anweisungen treten auch in Kaskaden auf: i f ( bexp1 ) { ... } e l s e i f ( bexp2 ) { ... } e l s e i f ( bexp3 ) { ... } e l s e { // o t h e r w i s e ... } RT (ICS @ UIBK) Programmiermethodik 55/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel If-Anweisung s t a t i c S t r i n g toRoman ( i n t x ) { String result ; i f ( x == 1 ) r e s u l t = "I" ; e l s e i f ( x == 5 ) r e s u l t = "V" ; e l s e i f ( x == 1 0 ) r e s u l t = "X" ; e l s e i f ( x == 5 0 ) r e s u l t = "L" ; e l s e i f ( x == 1 0 0 ) r e s u l t = "C" ; e l s e i f ( x == 5 0 0 ) r e s u l t = "D" ; e l s e i f ( x == 1 0 0 0 ) r e s u l t = "M" ; e l s e i f ( x == 5 0 0 0 ) r e s u l t = "A" ; e l s e r e s u l t = " unbekannt " ; return r e s u l t ; } RT (ICS @ UIBK) Programmiermethodik 56/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Dangling Else • Betrachte if (b1) if (b2) s1 else s2 • Problem: zu welchem if gehört das else? • if (b1) { if (b2) s1 else s2} oder if (b1) { if (b2) s1} else s2 • Festlegung: else gehört zum letztes freien if (was kein else hat) ⇒ if (b1) if (b2) s1 else s2 = if (b1) { if (b2) s1 else s2} RT (ICS @ UIBK) Programmiermethodik 57/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Switch • Alternative zu If-Kaskaden, Form: swi tch ( exp ) { case V a l u e 1 : s t m t s 1 ; break ; case V a l u e 2 : s t m t s 2 ; break ; ... case ValueN : stmtsN ; break ; default : stmts ; } • alle Werte Value1, ..., ValueN müssen verschieden sein • der default-Teil und die break-Anweisungen sind optional • Semantik • Ausdruck exp wird ausgewertet, liefert Wert w • Falls w einem ValueI entspricht, werden die Anweisungen stmtsI ausgeführt • Falls w keinem der Werte entspricht, werden (falls vorhanden) die default-Anweisungen stmts ausgeführt RT (ICS @ UIBK) Programmiermethodik 58/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel Switch-Anweisung s t a t i c S t r i n g toRomanSwitch ( i n t x ) { String result ; swi tch ( x ) { case 1 : r e s u l t = "I" ; break ; case 5 : r e s u l t = "V" ; break ; case 1 0 : r e s u l t = "X" ; break ; case 5 0 : r e s u l t = "L" ; break ; case 1 0 0 : r e s u l t = "C" ; break ; case 5 0 0 : r e s u l t = "D" ; break ; case 1 0 0 0 : r e s u l t = "M" ; break ; case 5 0 0 0 : r e s u l t = "A" ; break ; d e f a u l t : r e s u l t = " unbekannt " ; } return r e s u l t ; } RT (ICS @ UIBK) Programmiermethodik 59/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Wozu break in switch? swi tch ( exp ) { case V a l u e 1 : s t m t s 1 ; break ; ... case ValueN : stmtsN ; break ; default : stmts ; } • die einzelnen Fälle werden als Sprungmarken interpretiert: springe in die entsprechende Zeile • nach Sprung führe normale Anweisungsliste aus • ohne break würden immer alle nachfolgenden Fälle mit ausgeführt! • erlaubt Zusammenfassung von Fällen, Beispiel: swi tch ( 4 ) { case 4 : case 5 : x ∗= 2 ; // w i r d a u s g e f u e h r t case 7 : x += 9 ; break ; // w i r d a u s g e f u e h r t default : x = 0; // w i r d n i c h t a u s g e f . } RT (ICS @ UIBK) Programmiermethodik 60/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Vergleich If und Switch • Effizienz (mittlere Anzahl von Vergleichen bei n verschiedenen Fällen) • switch: zwischen konstant und log (n) • if -Kaskade: im Mittel n2 • Grund: switch wird intern mittels Tabelle implementiert • Flexibilität • if : beliebige boolesche Ausdrücke • switch: Test auf Konstanten mit folgenden Typen byte, short, int, char oder String (kein boolean, long, float oder double) ⇒ jedes switch kann durch if -Kaskade simuliert werden ⇒ if -Kaskade kann i.A. nicht durch ein switch simuliert werden RT (ICS @ UIBK) Programmiermethodik 61/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Schleifen • erlauben wiederholte Ausführung eines Programmteils • in Java 3 Varianten • while (bexp) { stmts; } 1. Evaluiere bexp 2a. Wenn Resultat true ist, dann führe stmts; aus und springe nach 1 2b. Sonst fahre mit Ausführung nach Schleife fort • do { stmts; } while (bexp); 1. Führe stmts; aus 2. Evaluiere bexp 3a. Wenn Resultat true ist, dann springe nach 1 3b. Sonst fahre mit Ausführung nach Schleife fort • for ( initStmt ; bexp; iterateStmt ) { stmts; } 1. Führe initStmt ; aus 2. Evaluiere bexp 3a. Bei Resultat true, führe stmts; iterateStmt ; aus, springe nach 2 3b. Sonst fahre mit Ausführung nach Schleife fort • { stmts; } kann durch einzelne Anweisung stmt; ersetzt werden • jede Variante kann durch jede andere Variante simuliert werden RT (ICS @ UIBK) Programmiermethodik 62/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel: Fibonacci-Zahlen wenn n = 0 0, • fib(n) = 1, wenn n = 1 fib(n − 1) + fib(n − 2), sonst • rekursive Lösung einfach, aber ineffizient s t a t i c long f i b R e c ( i n t r e t u r n ( n == 0 ? 0 ( n == 1 ? 1 fibRec (n − } RT (ICS @ UIBK) n) { : : 1) + f i b R e c ( n − 2 ) ) ) ; Programmiermethodik 63/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel: Fibonacci-Zahlen • mittels while-Schleife s t a t i c long f i b W h i l e ( i n t n ) { int i = 0; long f i b I = 0 ; // v a l u e o f f i b ( i ) long f i b I 1 = 1 ; // v a l u e o f f i b ( i +1); while ( i < n ) { long o l d F i b I = f i b I ; fibI = fibI1 ; fibI1 = oldFibI + fibI1 ; i ++; } return f i b I ; } RT (ICS @ UIBK) Programmiermethodik 64/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel: Fibonacci-Zahlen • mittels do ... while-Schleife s t a t i c long f i b D o W h i l e ( i n t n ) { i f ( n == 0 ) r e t u r n 0 ; int i = 0; long f i b I = 0 ; long f i b I 1 = 1 ; do { long o l d F i b I = f i b I ; fibI = fibI1 ; fibI1 = oldFibI + fibI1 ; i ++; } while ( i < n ) ; return f i b I ; } RT (ICS @ UIBK) Programmiermethodik 65/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel: Fibonacci-Zahlen • mittels for-Schleife s t a t i c long f i b F o r ( i n t n ) { long f i b I = 0 ; long f i b I 1 = 1 ; f o r ( i n t i = 0 ; i < n ; i ++) { long o l d F i b I = f i b I ; fibI = fibI1 ; fibI1 = oldFibI + fibI1 ; } return f i b I ; } RT (ICS @ UIBK) Programmiermethodik 66/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Continue und Break innerhalb von Schleifen • break; verlässt die Schleife vorzeitig • continue; springt direkt zum Schleifende (hinter stmts;) • Beispiel: f o r ( i n t i = 1 ; i <= 1 0 ; i ++) { i f ( i == 3 ) continue ; i ++; i f ( i == 9 ) break ; System . o u t . p r i n t ( i + " " ) ; } • continue und break . . . • können durch entsprechende Umformulierung eliminiert werden • können übermäßige Verschachtelung vermeiden • sollten sparsam verwendet werden (Lesbarkeit) RT (ICS @ UIBK) Programmiermethodik 67/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel mit und ohne Continue und Break int i ; f o r ( i = 1 ; i <= 1 0 ; i ++) { i f ( i == 3 ) c o n t i n u e ; i ++; i f ( i == 9 ) break ; System . o u t . p r i n t ( i + " " ) ; } int i ; boolean c o n t = t r u e ; f o r ( i = 1 ; i <= 10 && c o n t ; ) { i f ( i != 3 ) { i ++; i f ( i == 9 ) c o n t = f a l s e ; e l s e System . o u t . p r i n t ( i + " " ) ; } i f ( c o n t ) i ++; } RT (ICS @ UIBK) Programmiermethodik 68/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Übersicht Einführung in Java Historie und Features Grundlegende Elemente eines Java Programms (ohne OO) Datentypen Ausdrücke Anweisungen Arrays Methoden RT (ICS @ UIBK) Programmiermethodik 69/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Arrays • Zusammenfassung gleichartiger Elemente • Arrays haben fixe Länge • Länge ist nicht-negativer int-Wert ⇒ Nicht mehr als 2.147.483.647 Elemente • Länge wird bei Erzeugung fixiert • Arrayvariablen sind Referenzvariablen • Jedem Element ist Index vom Typ int zugewiesen • Index im Bereich 0, . . . , Länge-1 • Mehrdimensionale Arrays möglich RT (ICS @ UIBK) Programmiermethodik 70/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Deklaration von Arrays • [] ist Postfix-Typ Konstruktor • für jeden Typ type, ist type [] der Typ der Arrays mit Elementen vom Typ type • Beispiele: • int [] : Typ der Arrays von Integers • String [] : Typ der Arrays von Strings • double [][] : Typ der Arrays von Arrays von Doubles = Matrizen von Doubles (Array von Spaltenvektoren oder Array von Zeilenvektoren) • Deklaration wie üblich: int [] xs , ys ; String [][] foo; • oder in Postfix Notation: int x, xs [], matrix [][]; • übliche Deklaration bevorzugt: einheitliches Deklarationsschema type var1 , var2 , ...; RT (ICS @ UIBK) Programmiermethodik 71/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Erzeugung von Arrays • Erzeugung bei Deklaration int [] arr = new int[10]; • Spätere Erzeugung int [ ] arr ; ... a r r = new i n t [ 1 0 ] ; • Arrayelemente haben zunächst alle Wert • 0 – bei Arrays von Zahlen • ’\u0000’ – bei Arrays von Zeichen • false – bei Arrays von Booleans • null – bei allen anderen Arrays (null = Referenz auf nichts) • Länge des Arrays: arr . length • Anlegen von mehrdimensionalen Arrays: später RT (ICS @ UIBK) Programmiermethodik 72/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Erzeugung von Arrays mit Initialisierung • Erzeugung bei Deklaration int [] arr = {3, x + y, 3, 2, 1}; • Spätere Erzeugung String [ ] arr ; ... a r r = new S t r i n g [ ] { "foo" , h e l l o + w o r l d , "bar" } ; • Länge des Arrays = Anzahl der angegebenen Elemente RT (ICS @ UIBK) Programmiermethodik 73/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Zugriff auf Elemente • Elemente werden mittels Index addressiert • Index kann beliebiger Ausdruck exp sein, solange Typ mit int kompatibel ist • Syntax mittels eckigen Klammern: someArray[exp] • Lese- und Schreibzugriff möglich • someArray[5] = 7; • x = someArray[y] − 3; • someArray[y − x] += 17; • Wert des Index muss innerhalb des Indexbereichs (0, . . . , someArray.length − 1) liegen • Ansonsten gibt es Laufzeitfehler, d.h. Programm-Abbruch RT (ICS @ UIBK) Programmiermethodik 74/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Zuweisung und Vergleich von Arrays • Arrayvariable ist Referenz auf eigentliches Array • Bei Zuweisung wird nur Referenz kopiert, nicht das eigentliche Array • Beispiel: int [] a, b; a = new int[] {1,2,3}; b = a; b [1] = 5; a b RT (ICS @ UIBK) Programmiermethodik 75/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Zuweisung und Vergleich von Arrays • Arrayvariable ist Referenz auf eigentliches Array • Bei Zuweisung wird nur Referenz kopiert, nicht das eigentliche Array • Beispiel: int [] a, b; a = new int[] {1,2,3}; b = a; b [1] = 5; a 1 2 3 b RT (ICS @ UIBK) Programmiermethodik 75/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Zuweisung und Vergleich von Arrays • Arrayvariable ist Referenz auf eigentliches Array • Bei Zuweisung wird nur Referenz kopiert, nicht das eigentliche Array • Beispiel: int [] a, b; a = new int[] {1,2,3}; b = a; b [1] = 5; a 1 2 3 b RT (ICS @ UIBK) Programmiermethodik 75/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Zuweisung und Vergleich von Arrays • Arrayvariable ist Referenz auf eigentliches Array • Bei Zuweisung wird nur Referenz kopiert, nicht das eigentliche Array • Beispiel: int [] a, b; a = new int[] {1,2,3}; b = a; b [1] = 5; a 1 5 3 b RT (ICS @ UIBK) Programmiermethodik 75/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Zuweisung und Vergleich von Arrays • Arrayvariable ist Referenz auf eigentliches Array • Bei Zuweisung wird nur Referenz kopiert, nicht das eigentliche Array • Beispiel: int [] a, b; a = new int[] {1,2,3}; b = a; b [1] = 5; a 1 5 3 b • == ist Referenzvergleich wie bei Strings, nicht Wertevergleich! • Beispiel: int [] a = {1,2}, b = {1,2}; boolean c = a == b; //c == false RT (ICS @ UIBK) Programmiermethodik 75/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Zuweisung von Arrays (fortgesetzt) • Einschränkung bei Zuweisung von Arrays • Arrays müssen gleichen Typ haben; keine implizite Typanpassung! • int [] as , bs, cs ; ...; as = x > 3 ? bs : cs ; // okay • int [] is ; byte[] bs; ...; is = bs; // nicht okay • int [] is ; byte[] bs; ...; bs = is ; // nicht okay • Gründe i n t [ ] i s ; byte [ ] b s = { 1 0 } ; i s = b s ; i s [ 0 ] = 1 0 0 0 ; // n i c h t a u s r e i c h e n d P l a t z i n t [ ] i s = { 1 0 0 0 } ; byte [ ] b s ; b s = i s ; byte b = bs [ 0 ] ; // i m p l i z i t e Typanpassung RT (ICS @ UIBK) Programmiermethodik 76/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Iterieren über Arrays • Beispiel: Kopieren eines Arrays int orig [ ] ; . . . i n t copy [ ] = new i n t [ o r i g . l e n g t h ] ; f o r ( i n t i = 0 ; i < o r i g . l e n g t h ; i ++) copy [ i ] = o r i g [ i ] ; • Beispiel: Ausgabe eines Arrays f o r ( i n t i = 0 ; i < a r r a y . l e n g t h ; i ++) System . o u t . p r i n t ( a r r a y [ i ] + " " ) ; • Wenn man nur über die Elemente iterieren will, gibt es komfortable Iterator-Form ( for (type elemVariable : array ) { stmts; } ) f o r ( i n t elem : a r r a y ) System . o u t . p r i n t ( elem + " " ) ; RT (ICS @ UIBK) Programmiermethodik 77/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel: Sieb des Eratosthenes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 static int [ ] primes ( int n) { boolean [ ] i s P r i m e = new boolean [ n + 1 ] ; f o r ( i n t i = 2 ; i <= n ; i ++) isPrime [ i ] = true ; f o r ( i n t i = 2 ; i ∗ i <= n ; i ++) i f ( isPrime [ i ]) f o r ( i n t j = i + i ; j <= n ; j += i ) isPrime [ j ] = false ; int nrPrimes = 0; f o r ( boolean b : i s P r i m e ) i f ( b ) n r P r i m e s ++; i n t [ ] p r i m e s = new i n t [ n r P r i m e s ] ; i n t count = 0; f o r ( i n t i = 2 ; i <= n ; i ++) i f ( isPrime [ i ]) { p r i m e s [ c o u n t ] = i ; c o u n t ++; } return primes ; } RT (ICS @ UIBK) Programmiermethodik 78/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Freigabe des Speichers (Arrays, Strings, Objekte) • Freigabe erfolgt durch das System, nicht durch separate Anweisung • Wenn wenig freier Speicher vorhanden, wird Garbage Collector aktiv • nicht mehr erreichbare Speicherbereiche werden erfasst und freigegeben • Erreichbarkeit kann unterbunden werden • Zuweisung der null-Referenz (die auf nichts zeigt): arr = null; • Zuweisung eines anderen Wertes: arr = otherArr; RT (ICS @ UIBK) Programmiermethodik 79/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Freigabe des Speichers: Beispiel S t r i n g [ ] a , b ; S t r i n g s = "bar" ; a = new S t r i n g [ ] { "foo" , s } ; b = new S t r i n g [ ] { s , "com" , "dot" } ; b [1] = null ; a [1] = null ; b = a; a b s "bar" RT (ICS @ UIBK) Programmiermethodik 80/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Freigabe des Speichers: Beispiel S t r i n g [ ] a , b ; S t r i n g s = "bar" ; a = new S t r i n g [ ] { "foo" , s } ; b = new S t r i n g [ ] { s , "com" , "dot" } ; b [1] = null ; a [1] = null ; b = a; a b • • s "foo" RT (ICS @ UIBK) "bar" Programmiermethodik 80/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Freigabe des Speichers: Beispiel S t r i n g [ ] a , b ; S t r i n g s = "bar" ; a = new S t r i n g [ ] { "foo" , s } ; b = new S t r i n g [ ] { s , "com" , "dot" } ; b [1] = null ; a [1] = null ; b = a; a b • • • • • s "foo" RT (ICS @ UIBK) "bar" Programmiermethodik "com" "dot" 80/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Freigabe des Speichers: Beispiel S t r i n g [ ] a , b ; S t r i n g s = "bar" ; a = new S t r i n g [ ] { "foo" , s } ; b = new S t r i n g [ ] { s , "com" , "dot" } ; b [1] = null ; a [1] = null ; b = a; a b • • • • • s "foo" RT (ICS @ UIBK) "bar" Programmiermethodik "com" "dot" 80/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Freigabe des Speichers: Beispiel S t r i n g [ ] a , b ; S t r i n g s = "bar" ; a = new S t r i n g [ ] { "foo" , s } ; b = new S t r i n g [ ] { s , "com" , "dot" } ; b [1] = null ; a [1] = null ; b = a; a b • • • • • s "foo" RT (ICS @ UIBK) "bar" Programmiermethodik "dot" 80/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Freigabe des Speichers: Beispiel S t r i n g [ ] a , b ; S t r i n g s = "bar" ; a = new S t r i n g [ ] { "foo" , s } ; b = new S t r i n g [ ] { s , "com" , "dot" } ; b [1] = null ; a [1] = null ; b = a; a b • • • • • s "foo" RT (ICS @ UIBK) "bar" Programmiermethodik "dot" 80/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Freigabe des Speichers: Beispiel S t r i n g [ ] a , b ; S t r i n g s = "bar" ; a = new S t r i n g [ ] { "foo" , s } ; b = new S t r i n g [ ] { s , "com" , "dot" } ; b [1] = null ; a [1] = null ; b = a; a b • • • • • s "foo" RT (ICS @ UIBK) "bar" Programmiermethodik "dot" 80/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Freigabe des Speichers: Beispiel S t r i n g [ ] a , b ; S t r i n g s = "bar" ; a = new S t r i n g [ ] { "foo" , s } ; b = new S t r i n g [ ] { s , "com" , "dot" } ; b [1] = null ; a [1] = null ; b = a; a b • • s "foo" RT (ICS @ UIBK) "bar" Programmiermethodik "dot" 80/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Freigabe des Speichers: Beispiel S t r i n g [ ] a , b ; S t r i n g s = "bar" ; a = new S t r i n g [ ] { "foo" , s } ; b = new S t r i n g [ ] { s , "com" , "dot" } ; b [1] = null ; a [1] = null ; b = a; a b • • s "foo" RT (ICS @ UIBK) "bar" Programmiermethodik 80/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Mehrdimensionale Arrays • Arrays können beliebig viele Dimensionen haben. • Beispiel: 2-dimensionales Array • int [][] matrix = new int [3][2]; • int [][] matrix2 = { { 1, 2 }, { 3, 4 }, { 5, 6 } }; • int [][] matrix3 = new int [3][]; // = new int [][]{ null , null , null } • Zugriff • x = matrix2 [1][0]; // 3 • arr = matrix2 [2]; // [5,6] • Realisierung in Java matrix2 • 1 RT (ICS @ UIBK) 2 • • 3 4 5 Programmiermethodik 6 81/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel: Pascalsches Dreieck • erzeugt nicht-rechteckiges, 2-dimensionales Array • k-te Zeile = Koeffizienten von (x + y )k • 3. Zeile = 1 3 3 1 ⇒ (x + y )3 = 1 · x 3 y 0 + 3 · x 2 y 1 + 3 · x 1 y 2 + 1 · x 0 y 3 1 static int [ ] [ ] pascal ( int n) { 2 i n t p [ ] [ ] = new i n t [ n ] [ ] ; 3 f o r ( i n t i = 0 ; i < n ; i ++) { 4 p [ i ] = new i n t [ i + 1 ] ; 5 f o r ( i n t j = 0 ; j <= i ; j ++) { 6 i f ( ( j == 0 ) | | ( j == i ) ) { 7 p [ i ] [ j ] = 1; 8 } else { 9 p [ i ] [ j ] = p [ i − 1 ] [ j − 1] + p [ i − 1 ] [ j ] ; 10 } 11 } 12 } 13 return p ; 14 } RT (ICS @ UIBK) Programmiermethodik 82/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Übersicht Einführung in Java Historie und Features Grundlegende Elemente eines Java Programms (ohne OO) Datentypen Ausdrücke Anweisungen Arrays Methoden RT (ICS @ UIBK) Programmiermethodik 83/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Unterprogramme • Teile eines Programms können an einer anderen Stelle als Unterprogramm formuliert werden • Unterprogramme können in Anweisungsfolge oder Ausdruck aufgerufen werden • • • • Verzweigung zum Unterprogramm Abarbeitung des Unterprogramms Nach Abarbeitung Rückkehr zur Aufrufstelle Eventuell Ergebnis weiterverwenden RT (ICS @ UIBK) Programmiermethodik 84/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Arten von Unterprogrammen Gebe Pascal’s Dreieck aus Unterscheidung nach Aufgabe • Prozeduren • Unterprogramme, die Anweisungen (mit Seiteneffekt) ausführen • kein Rückgabewert (in Java: void) • Funktionen • Unterprogramme, die Anweisungen ausführen • mit Rückgabewert (in Java: type 6= void) Unterscheidung nach Zugehörigkeit • Unterprogramme Liefere Pascal’s Dreieck als Array • Eigenständiger Teil des Programms • C-Funktion class Name { ... someMethod ...} • Nicht in Java • Methoden • Gehören einer Klasse an • Java-Methoden RT (ICS @ UIBK) Programmiermethodik 85/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Java Methoden • in Java spricht man nur von Methoden • in Vorlesung trotzdem manchmal Unterscheidung Prozedur / Funktion, um Aufgabe klarzustellen • zwei Arten von Methoden • Statische Methoden • Gehören zur Klasse • Details in diesem Abschnitt • gekennzeichnet mit Schlüsselwort static • Objektbezogene Methoden • später, im Kapitel über Objektorientierung RT (ICS @ UIBK) Programmiermethodik 86/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Struktur einer Methode • Methode = Methodenkopf + Methodenrumpf • Methodenkopf: static returnType methodName (type1 parameterName1, ...) • Methodenrumpf: { stmts; } • Signatur einer Methode: Methodennamen + Parametertyp-Liste • methodName(type1, ...) • • • • formale Parameter = Namen der Parameter parameterName1, ... aktueller Parameter = Werte beim Aufruf einer Methode Aufruf von Methode initialisiert formale Param. mit aktuellen Param. Beispiel s t a t i c i n t f o o ( i n t x ) { // f o r m a l e r P a r a m e t e r : x x ∗= 2 ; r e t u r n ( x +5); } ... i n t y = f o o ( 5 + 3 ) ; // a k t u e l l e r P a r a m e t e r : 5 + 3 RT (ICS @ UIBK) Programmiermethodik 87/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Arten der Parameterübergabe static int foo ( int x ) { x ∗= 2 ; r e t u r n ( x +5); } Betrachte Aufruf foo(exp) • Call-by-value • exp wird ausgewertet zu einem Wert w • Kopie von w wird an Methode übergeben • Änderungen am formalen Parameter x ändert nichts am aktuellen Parameter • Call-by-reference • exp muss eine Referenz sein (z.B. Variable, kein foo(2) möglich) • Änderungen am formalen Parameter x ändern aktuellen Parameter • Beispiel: int x = 1; int y = foo(x); int z = foo(x); • Call-by-value: x = ,y = ,z = • Call-by-reference: x = , y = , z = RT (ICS @ UIBK) Programmiermethodik 88/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Parameterübergabe in Java • immer call-by-value! • bei Parameterübergabe wird Kopie überzeugt • es gelten Kompatibilitätsregeln: Typ eines aktuellen Parameters muss durch implizite Typanpassung in Typ des formalen Parameters konvertiert werden können • void foo(int x) { long y = 0; foo(y ); } // nicht okay • void foo(long x) { int y = 0; foo(y ); } // okay • void foo( String x) { int y = 0; foo(y ); } // nicht okay (implizite Typanpassung nach String nur bei + !) RT (ICS @ UIBK) Programmiermethodik 89/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Parameterübergabe von Referenzen • Kopie ist nicht gleich Kopie • Kopie von Basisdatentyp = Kopie des Wertes • nichts kann verändert werden • Kopie von anderen Typen = Kopie der Referenz • Referenz kann nicht verändert werden • das referenzierte Objekt kann aber verändert werden RT (ICS @ UIBK) Programmiermethodik 90/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel Übergabe von Referenzen s t a t i c void t e s t ( ) { int [ ] x = {4 ,5 ,6}; int [ ] y = x ; System . o u t . p r i n t l n ( sum ( y ) ) ; // 15 System . o u t . p r i n t l n ( x == y ) ; // t r u e // x = // y = } s t a t i c i n t sum ( i n t [ ] a ) { f o r ( i n t i = 1 ; i < a . l e n g t h ; i ++) a [ 0 ] += a [ i ] ; return a [ 0 ] ; } RT (ICS @ UIBK) Programmiermethodik 91/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Rückgabewert von Funktionen • • • • mittels return exp; führen zum direktem Abbruch der Funktion return; zum vorzeitigen Abbruch in einer Prozedur Beispiele: static int fact ( int n) { r e t u r n ( n <= 1 ? 1 : n ∗ f a c t ( n − 1 ) ) ; } s t a t i c v o i d p r i n t F i l e ( S t r i n g name ) { boolean f i l e O p e n e d ; . . . // t r y t o open f i l e w i t h name i f (! fileOpened ) { return ; } . . . // p r i n t c o n t e n t o f f i l e and c l o s e i t } RT (ICS @ UIBK) Programmiermethodik 92/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Lokale und globale Variablen • lokale Variablen • sind Parameter und Variablen, die innerhalb Methode deklariert werden • sind nicht in anderen Methoden(aufrufen) sichtbar • Lebensdauer: • werden angelegt, wenn Methode aufgerufen wird • werden freigegeben, wenn Methode verlassen wird • globale Variablen (Klassenvariablen) • sind in jeder Methode der Klasse sichtbar • werden mit Standard-Werten initialisiert (0, false , null) • Lebensdauer: • werden angelegt, wenn Klasse erstmalig genutzt wird • werden freigegeben, wenn Programm beendet wird c l a s s MyClass { s t a t i c i n t g l o b a l V a r = 5 ; s t a t i c boolean g l o b a l B o o l ; s t a t i c void foo ( ) { int localVar = 3; i f ( g l o b a l B o o l ) { g l o b a l V a r ++; } . . . } } RT (ICS @ UIBK) Programmiermethodik 93/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Verwendung lokaler / globaler Variablen • Wenn möglich, Variablen immer lokal deklarieren • keine Namenskonflikte mit anderen Methoden • keine Probleme bei Veränderung einer gemeinsam genutzten globalen Variable • Globale Variablen verwenden, wenn Wert über mehrere Methoden-Aufrufe hinweg verfügbar sein muss RT (ICS @ UIBK) Programmiermethodik 94/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel: globale Variablen für statistische Zwecke class Fibonacci { s t a t i c int count ; static int f i b ( int n) { c o u n t ++; r e t u r n ( n == 0 ? 0 : ( n == 1 ? 1 : f i b ( n − 1) + f i b ( n − 2 ) ) ) ; } s t a t i c void t e s t ( i n t n ) { count = 0; fib (n ); System . o u t . p r i n t l n ( "To compute fib(" + n + "), " + "we invoked fib " + c o u n t + " many times " ) ; } } RT (ICS @ UIBK) Programmiermethodik 95/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Überladen von Methoden • Idee: benutze gleichen Methodennamen für unterschiedliche Parameter • Bereits bekannt bei Operatoren: "a" + "b" , 3 + 2 , − x , x − y • in Java: gleicher Methodenname gestattet, solange Signatur unterschiedlich ist (Erinnerung: Signatur = Methodenname + Liste der Parametertypen) • • • • Unterschied in Typen, Unterschied in Reihenfolge der Typen, oder Unterschied in Anzahl der Parameter (Rückgabewert spielt keine Rolle beim Überladen) • falls gleicher Methodenname mindestens zweimal verwendet wurde, nennt man diese Methoden überladen RT (ICS @ UIBK) Programmiermethodik 96/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel: Überladen s t a t i c v o i d f o o ( i n t x ) { System . o u t . p r i n t l n ( "i" ) ; } s t a t i c v o i d f o o ( double x ) { . . . "d" ) ; } s t a t i c v o i d f o o ( i n t x , i n t y ) { . . . "ii" ) ; } s t a t i c v o i d f o o ( i n t x , double y ) { . . . "id" ) ; } s t a t i c v o i d f o o ( double x , i n t y ) { . . . "di" ) ; } s t a t i c v o i d f o o ( char x , long y , i n t z ) { . . . "cli" ) ; } s t a t i c v o i d f o o ( char x , i n t y , long z ) { . . . "cil" ) ; } s t a t i c void t e s t ( ) { foo (10); f o o ( 1 0D ) ; f o o ( 1 0 , ’a’ ) ; f o o ( 1 0 , 10D ) ; foo (10F , 1 0 ) ; f o o ( ’a’ , 1 0 , 1 0 ) ; } RT (ICS @ UIBK) Programmiermethodik 97/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Methoden mit variabler Parameteranzahl • normalerweise haben Methode festen Anzahl von Parametern • manchmal beliebige Anzahl von Parametern eines Typs komfortabel • herkömmliche Lösung mittels Arrays: static int sum(int[] values ) { stmts; } • komfortable Lösung mittels varargs-Parameter “...” static int sum(int ... values ) { stmts; } • innerhalb der Methode kann values wie Array-Typ behandelt werden ⇒ Anweisungen in beiden sum-Methoden ist identisch • varargs-Parameter muss immer an letzter Stelle stehen • beim Aufruf wird intern ein Array erstellt: int x = sum(1,2,y,7); ⇒ int x = sum(new int[]{1,2,y,7}); RT (ICS @ UIBK) Programmiermethodik 98/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel: Varargs (+ Überladen) s t a t i c void p r i n t ( i n t i , i n t j ) { System . o u t . p r i n t l n ( " Integer " + i + " " + j ) ; } s t a t i c void p r i n t ( i n t i , i n t . . . v a l u e s ) { System . o u t . p r i n t ( " Integer " + i + ", " ) ; System . o u t . p r i n t l n ( "# Varargs : " + v a l u e s . l e n g t h ) ; } s t a t i c i n t sum ( i n t . . . v a l u e s ) { int r e s u l t = 0; for ( int x : values ) r e s u l t += x ; return r e s u l t ; } ... System . o u t . p r i n t l n ( sum ( 1 , 2 , 3 ) ) ; System . o u t . p r i n t l n ( sum ( 1 , 2 , 3 , 4 , 5 ) ) ; System . o u t . p r i n t l n ( sum ( ) ) ; print (1); p r i n t (1 , 2); p r i n t (1 , 2 , 3); RT (ICS @ UIBK) Programmiermethodik 99/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Vordefinierte Methoden und Konstanten • Java bietet etliche statische Methoden in Bibliothek an • gehören zur Klasse • typischer Aufruf: ClassName.methodName(...) • Beispiel: Math.sqrt(10.0) , . . . • neben statischen Methoden gibt es auch globale Konstanten (und deren Methoden) • typische Aufrufe: ClassName.CONSTANT_NAME und ClassName.objectName.methodName(...) • Beispiel: Math.PI , System.out. println (7) , . . . RT (ICS @ UIBK) Programmiermethodik 100/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiele für Klassenmethoden und Konstanten • System • System.out. println (...) , System.err . println (...) , . . . • Math • Math.random() , Math.sin(double) , Math.E , . . . • Integer • Integer .MAX_VALUE , Integer .MIN_VALUE , . . . • Arrays • viele überladene Methoden (hier für short) • Arrays .copyOf(short [], int length) • Arrays . equals(short [], short []) • Arrays . binarySearch(short [], short key) • Arrays . sort (short []) • Arrays . toString (short []) RT (ICS @ UIBK) Programmiermethodik 101/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Importieren von Klassen (Kurzversion) • manche Klassen sind immer verfügbar (Math, System, String, . . . ) • andere müssen erst importiert werden • 2 Möglichkeiten zum Import: • zu Beginn (am Anfang der Datei) • import java . util . Arrays ; // Klasse Arrays im Paket java . util • import java . util .∗; // alles aus java . util • ... int [] x = Arrays.copyOf(y, y. length ); ... • direkt im Code (auch zur Auflösung von Mehrdeutigkeiten) • RT (ICS @ UIBK) ... int [] x = java. util . Arrays .copyOf(y, y. length ); ... Programmiermethodik 102/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Beispiel: Import von Klassen import j a v a . u t i l . A r r a y s ; // i m p o r t kommt v o r c l a s s class ArrayTest { s t a t i c void t e s t ( ) { double [ ] a = { 1 . 5 , Math . c o s ( Math . PI ) , 0 } ; double [ ] b = {−1, 0 , 1 . 5 } ; Arrays . sort (a ) ; System . o u t . p r i n t l n ( a == b ) ; System . o u t . p r i n t l n ( A r r a y s . e q u a l s ( a , b ) ) ; System . o u t . p r i n t l n ( a ) ; System . o u t . p r i n t l n ( A r r a y s . t o S t r i n g ( a ) ) ; System . o u t . p r i n t l n ( Math . s i n ( Math . PI ) ) ; } } RT (ICS @ UIBK) Programmiermethodik ... 103/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Dokumentation der Klassen • Startpunkt: API-Dokumentation http://docs.oracle.com/javase/7/docs/api/ • Informationen • für jedes Paket • Liste der Klassen • für jede Klasse • Beschreibung der Klasse • Liste der Methoden • für jede Methode • Kurzbeschreibung im Überblick • Längere Beschreibung mit Erklärung der Parameter, . . . RT (ICS @ UIBK) Programmiermethodik 104/613 Einführung in Java Grundlegende Elemente eines Java Programms (ohne OO) Nutzen von Methoden • Wiederverwendung von Code • Ausgliedern häufig benutzter Programmteile • spart Schreibarbeit • macht Programme kürzer • Definition benutzerspezifischer Operationen • Programmiersprache “anpassen” • Strukturierung von Programmen • Zusammenfassen von Anweisungen, die logisch zusammengehören • Erleichtert Programmverständnis RT (ICS @ UIBK) Programmiermethodik 105/613 Objektorientierung Übersicht Objektorientierung Allgemeine Grundlagen Objekte und Klassen Objekte, Klassen und Methoden in Java String-Klasse Wrapper-Klassen RT (ICS @ UIBK) Programmiermethodik 106/613 Objektorientierung Allgemeine Grundlagen Übersicht Objektorientierung Allgemeine Grundlagen Objekte und Klassen Objekte, Klassen und Methoden in Java String-Klasse Wrapper-Klassen RT (ICS @ UIBK) Programmiermethodik 107/613 Objektorientierung Allgemeine Grundlagen Motivation • Bisher: Datentypen, Anweisungen, Arrays, Unterprogramme • Anwendung: Algorithmen implementieren, kleine Programme • Problem: Große Programme • mit bisherigen Mitteln machbar, aber nicht sinnvoll • zu große Komplexität • Komplexität (hier: nicht Laufzeit!) • Schwierigkeiten • Komplizierte Algorithmen • Komplexe Software: Verknüpfung vieler Funktionen (die aber meist einfach sind) • Probleme bei Softwareentwicklung • Viele Funktionen müssen organisiert werden • Anforderung können sich ändern RT (ICS @ UIBK) Programmiermethodik 108/613 Objektorientierung Allgemeine Grundlagen Lösungen für Komplexität • Beachte Prinzipien bei Programmierung • Beispiele • abgeschlossener Programmteil (Modul) hat nur eine Verantwortung • Wiederholungen vermeiden • Trennung von Schnittstelle und Implementierung • Techniken der Objektorientierung unterstützen diese Prinzipien • Einschränkung: Objektorientierung führt nicht automatisch zu besserer Software RT (ICS @ UIBK) Programmiermethodik 109/613 Objektorientierung Allgemeine Grundlagen Grundelemente der Objektorientung • Datenkapselung • Vererbung • Polymorphie RT (ICS @ UIBK) Programmiermethodik 110/613 Objektorientierung Allgemeine Grundlagen Datenkapselung • In strukturierter Programmierung (z.B. C) sind Daten und Routinen getrennt • Objektorientierung verändert dies • • • • Daten gehören zu einer Einheit (Objekt) Direkter Zugriff ist nicht erlaubt (sollte nicht erlaubt sein) Klar definierte Schnittstelle (Operationen) des Objekts wird verwendet Objekt kann selbst für Konsistenz der Daten sorgen ⇒ Konsistenz der Daten ist gewährt ⇒ Anpassungen der internen Struktur benötigt keine Anpassung beim Aufrufer RT (ICS @ UIBK) Programmiermethodik 111/613 Objektorientierung Allgemeine Grundlagen Ohne Datenkapselung Aufrufer C Probleme: Aufrufer B Änderung der internen Darstellung angepasst werden radius *= 7; x -= 7; Aufrufer A • bei Änderung der internen Struktur ist evtl. Konsistenz nicht gewährleistet x += 3; int x; int y; int radius; RT (ICS @ UIBK) • Alle Aufrufe müssen bei Programmiermethodik 112/613 Objektorientierung Allgemeine Grundlagen Mit Datenkapselung Aufrufer C Aufruf Operation resize Aufrufer B radius *= 7; x -= 7; x += 3; int x; int y; int radius; RT (ICS @ UIBK) Aufrufer A Aufruf Aufruf Operation move Programmiermethodik 113/613 Objektorientierung Allgemeine Grundlagen Vererbung • Vererbung von Spezifikation • Gemeinsamkeiten werden in abstrakten Spezifikation zusammengefasst • Klassen implementieren diese Spezifikation • Vererbung von Implementierung • Ermöglicht neue Klassen aus existierenden Klassen abzuleiten • Es werden nur Unterschiede zwischen der abgeleiteten Klasse und der Basisklasse angegeben • Man spricht auch von • Unterklasse (abgeleitete Klasse) • Oberklasse (Basisklasse) • Nutzen der Vererbung • Ersparnis beim Programmieraufwand • Vereinfachung von Programmänderungen RT (ICS @ UIBK) Programmiermethodik 114/613 Objektorientierung Allgemeine Grundlagen Polymorphie • Polymorphie = Vielgestaltigkeit • Bei Programmiersprachen • Variable (oder Routine) kann abhängig von Verwendung unterschiedliche Datentypen annehmen • Ermöglicht flexible Software RT (ICS @ UIBK) Programmiermethodik 115/613 Objektorientierung Allgemeine Grundlagen Objektorientierung allgemein • Objektorientierung: Paradigma für • Analyse, • Entwurf und • Implementierung von objektorientierten Systemen • Teilaspekte sind • Objektorientierte Analyse (OOA), • Objektorientiertes Design (OOD) und • Objektorientierte Programmierung (OOP) • Hauptteil dieser Vorlesung • Grundlagen der objektorientierten Programmierung (in Java) • Einführung in das objektorientierte Design RT (ICS @ UIBK) Programmiermethodik 116/613 Objektorientierung Allgemeine Grundlagen OOA, OOD und OOP • Objektorientierte Analyse • Eingabe: informelle Anforderungen (vom Kunden) • Ausgabe: konzeptuelles Modell (konkretisierte Anforderungen, Ablaufdiagramme, grober Entwurf) • Objektorientierte Design • Eingabe: konzeptuelles Modell • Ausgabe: konkretes Modell (detaillierte Aufbau des Systems, Berücksichtigung von Seitenbedingungen wie Plattform, Programmiersprache, . . . ) • Objektorientierte Programmierung • Eingabe: konkretes Modell • Ausgabe: Lauffähiger Code in objektorientierter Sprache RT (ICS @ UIBK) Programmiermethodik 117/613 Objektorientierung Objekte und Klassen Übersicht Objektorientierung Allgemeine Grundlagen Objekte und Klassen Objekte, Klassen und Methoden in Java String-Klasse Wrapper-Klassen RT (ICS @ UIBK) Programmiermethodik 118/613 Objektorientierung Objekte und Klassen Basis der Objektorientierung • Objekt • Objekt ist Bestandteil eines Programms • Objekt enthält Zustände • Objekt stellt anderen Objekten Operationen zur Verfügung • Objekt legt fest, wie es auf eine Operation reagiert • Objekt ist Datenkapsel (engl. Encapsulation) • Objekt bündelt Daten (Zustände) und Funktionalität (Operationen) • Benutzer (Aufrufer) muss nur wissen was das Objekt macht • Das wie ist nicht interessant (verringert Komplexität!) RT (ICS @ UIBK) Programmiermethodik 119/613 Objektorientierung Objekte und Klassen Datenkapsel • Objekt hat Eigenschaften • Beispiel: Stoppuhr speichert verstrichene Zeit und Status (läuft Zeit) • Objekt besitzt Daten, die nur von ihm verändert werden (verstrichene Zeit) • Eigenschaften (Attribute) • sind von außen erfragbar • direkte Abfrage sollte aber vermieden werden • können auf den Daten basieren oder errechnet werden (abgeleitete Eigenschaften) • Eigenschaften können voneinander abhängig sein RT (ICS @ UIBK) Programmiermethodik 120/613 Objektorientierung Objekte und Klassen Operationen (Methoden) • Operationen • Operationen spezifiziert Funktionalität eines Objekts • Objekt sichert Aufrufer zu, dass bei Aufruf die Operation ausführt wird • Schnittstelle = Menge der Operationen eines Objekts • Realisierung von Operationen in Java: Methoden • Geheimnisprinzip (information hiding) • Daten sollten privat, Operationen (Methoden) öffentlich sein • Klassen aus Daten und Methoden sind die Grundbausteine der objektorientierten Programmierung RT (ICS @ UIBK) Programmiermethodik 121/613 Objektorientierung Objekte und Klassen Klassen • Klasse beschreibt gemeinsame Eigenschaften und Operationen einer Menge von gleichartigen Objekten • Struktur und Verhalten der Objekte einer Klasse sind gleich (unterscheiden sich nur in den Zuständen) • Klassen stellen Konstruktionsplan für bestimmte Objekte dar • In den meisten objektorientierten Programmiersprachen ist jedes Objekt einer Klasse zugeordnet • Klassifizierung • Zuordnung von Objekten zu Klassen • Relevante Gemeinsamkeiten von Objekten identifizieren • Objekte mit Gemeinsamkeiten in eine Klasse geben RT (ICS @ UIBK) Programmiermethodik 122/613 Objektorientierung Objekte und Klassen Beispiel Klassifizierung (aus OOP, Lahmes und Rayman) RT (ICS @ UIBK) Programmiermethodik 123/613 Objektorientierung Objekte und Klassen Exemplare (Instanzen, instances) • Objekte sind Exemplare der Klassen, zu denen sie gehören • Klasse kann mehrere Exemplare haben • Objekte können Exemplare mehrerer Klassen sein • In vielen Programmiersprachen sind Objekte nur Exemplare einer Klasse RT (ICS @ UIBK) Programmiermethodik 124/613 Objektorientierung Objekte und Klassen Einfaches Beispiel • Klasse Sparbuch • Attribute/Eigenschaften: Kontonummer, Inhaber, Saldo • Operationen: Einzahlen, Auszahlen • Objekte (Exemplare von Klasse Sparbuch) • SB1 = ein Sparbuch (129032, Amy Arm, 5,30 e) • SB2 = ein Sparbuch (139010, Rudi Reich, 1.000.000,00 e) • ... • Beispiel Operation • SB1.Einzahlen(300 e) ⇒ SB1 = ein Sparbuch (129032, Amy Arm, 305,30 e) RT (ICS @ UIBK) Programmiermethodik 125/613 Objektorientierung Objekte, Klassen und Methoden in Java Übersicht Objektorientierung Allgemeine Grundlagen Objekte und Klassen Objekte, Klassen und Methoden in Java String-Klasse Wrapper-Klassen RT (ICS @ UIBK) Programmiermethodik 126/613 Objektorientierung Objekte, Klassen und Methoden in Java Klassen • Klassen sind selbst definierte Datentypen • Erlauben mehrere Elemente zu neuem Element zusammenzufassen und unter gemeinsamen Namen anzusprechen • Können analog zu den eingebauten Datentypen verwendet werden • Vergleiche dazu Arrays (Zusammenfassung gleichartiger Elemente) • Beispiel - Bankkonto (sehr stark vereinfacht) • Daten: Name, Betrag • Operationen, die man auf so ein Konto ausführen möchte • Aufteilung auf Dateien • Mehrere Klassen pro Datei sind möglich • Jede Klasse sollte aber in eigener Datei sein RT (ICS @ UIBK) Programmiermethodik 127/613 Objektorientierung Objekte, Klassen und Methoden in Java Deklaration • Einfacher Ansatz für ein Bankkonto p u b l i c c l a s s Account { p r i v a t e S t r i n g name ; p r i v a t e double amount ; p u b l i c v o i d d e p o s i t ( double money ) { . . . } ... } • Variablen werden als Felder, Attribute, Membervariablen, • • • • Instanzvariablen oder Objektvariablen bezeichnet Operationen (Methoden) und Objektvariablen werden ohne Schlüsselwort static deklariert Klasse Account kann wie jeder andere Datentyp verwendet werden Klassenname ist Typ, und kann in Deklarationen verwendet werden Beispiel: Account x, y; deklariert 2 Variablen, die Objekte vom Typ Account referenzieren können RT (ICS @ UIBK) Programmiermethodik 128/613 Objektorientierung Objekte, Klassen und Methoden in Java Zugriffsattribute in Java (ein erster Überblick) • public • Zugriff von überall erlaubt (bei Objektvariablen: lesend und schreibend) • private • Zugriff nur aus Methoden derselben Klasse erlaubt • Kein Attribut (default) • Zugriff aus Methoden beliebiger Klassen desselben Pakets erlaubt • Details über Pakete: später RT (ICS @ UIBK) Programmiermethodik 129/613 Objektorientierung Objekte, Klassen und Methoden in Java Objekterzeugung • Erzeugung mit new x = new Account ( ) ; y = new Account ( ) ; x und y zeigen nun auf Account-Objekte • Beide Objekte haben gleiche Struktur, aber unterschiedliche Identität (wird intern verwaltet) • Identität • Objekte haben immer eigene Identität • Zwei Objekte können dadurch immer unterschieden werden, auch wenn sie den gleichen Zustand haben (mittels ==) • Allgemeines Beispiel: Zwei gleiche Fahrräder (neu, gleiches Modell und Farbe) haben gleichen Zustand sind aber trotzdem unterschiedlich (Identität ∼ Seriennummer) RT (ICS @ UIBK) Programmiermethodik 130/613 Objektorientierung Objekte, Klassen und Methoden in Java Automatische Initialisierung • Objektvariablen werden automatisch initialisiert (0, false, ’\u0000’, null) • Objektvariablen können aber auch wie lokale Variablen initialisiert werden • Beispiel p u b l i c c l a s s Account { p r i v a t e S t r i n g name ; // = n u l l p r i v a t e double amount = 5 ; // 5 EUR S t a r t g u t h a b e n ... } RT (ICS @ UIBK) Programmiermethodik 131/613 Objektorientierung Objekte, Klassen und Methoden in Java Verwendung • Nach Erzeugung kann die Variable vom Typ Account verwendet werden • Auf Objektvariablen und Methoden (vor allem!) kann durch Qualifikation zugegriffen werden • someObject.objectVariabeName • someObject.methodName(...) • Wichtig: Direkter Zugriff auf Objektvariablen sollte nur in seltenen Fällen durchgeführt werden (Datenkapselung) • Negativbeispiel p u b l i c c l a s s Account { p r i v a t e S t r i n g name ; p u b l i c double amount ; // d a n g e r o u s ... } Account x = new Account ( ) ; ... x . amount = 1_000_000_000.00; RT (ICS @ UIBK) Programmiermethodik 132/613 Objektorientierung Objekte, Klassen und Methoden in Java this-Referenz • jedes Objekt hat eine this-Referenz • Referenz auf sich selbst • ist in jeder Methode automatisch definiert • damit können Objektvariablen von lokalen Variablen unterschieden werden ⇒ Objektvariablen und lokale Variablen können den gleichen Bezeichner haben RT (ICS @ UIBK) Programmiermethodik 133/613 Objektorientierung Objekte, Klassen und Methoden in Java Beispiel: Stack Dateien: Stack1, Stack2, Stack3, StackApplication RT (ICS @ UIBK) Programmiermethodik 134/613 Objektorientierung Objekte, Klassen und Methoden in Java Zuweisung • Objektreferenzen können einander zugewiesen werden, falls sie den gleichen Typ haben • Typen werden durch denselben Namen bezeichnet (Namensäquivalenz) • nicht in allen Programmiersprachen gleich • es gibt auch Strukturäquivalenz (Typen sind gleich, wenn sie gleiche Struktur haben) • null darf jeder Objektvariable zugewiesen werden • Beispiel Account x = new Account ( ) , y = n u l l ; y = x; y und x referenzieren dasselbe Objekt ⇒ Jede Änderung der Objektvariablen ist bei x und y sichtbar (wie bei Arrays) RT (ICS @ UIBK) Programmiermethodik 135/613 Objektorientierung Objekte, Klassen und Methoden in Java Vergleiche • Objekte können mit == und != verglichen werden ⇒ Vergleicht nur Referenzen und nicht die Werte (wie bei Arrays und Strings)! • Will man vergleichen, ob Objekte inhaltlich gleich sind • schreibe eigene Vergleichsmethode • muss einzelne Objektvariablen vergleichen • genauer Vergleich kann noch komplizierter sein (wird im Kapitel über die Vererbung noch genau besprochen)! RT (ICS @ UIBK) Programmiermethodik 136/613 Objektorientierung Objekte, Klassen und Methoden in Java Getter- und Setter-Methoden • Private Objektvariable ist von außen nicht erreichbar • Wenn man die Werte lesen bzw. ändern möchte: • Getter- bzw. Setter-Methode (Accessors, Mutators) • Beispiel p r i v a t e t y p e name ; ... p u b l i c t y p e getName ( ) { . . . } p u b l i c v o i d setName ( t y p e name ) { . . . } • Vorteile durch Methoden • Kontrolle der übergebenen Werte • Hilfsmittel zur Fehlersuche • Setter/Getter für scheinbare Datenelemente • Interne Maßnahmen (Optimierung) verbergen RT (ICS @ UIBK) Programmiermethodik 137/613 Objektorientierung Objekte, Klassen und Methoden in Java Getter- und Setter-Methoden • Getter- und Setter-Methoden sind nur einfachste Möglichkeit, auf Objektvariablen zuzugreifen • Intensiver Gebrauch von Getter- und Setter-Methoden ist kein Zeichen von Objektorientierung • Deutet eher auf einen fragwürdigen OO-Entwurf hin • Objekt verkommt zu Datencontainer, keine Objektorientierung! • Verhalten des Objekts kann zu sehr von anderen Klassen gesteuert werden RT (ICS @ UIBK) Programmiermethodik 138/613 Objektorientierung Objekte, Klassen und Methoden in Java Beispiel: Rationale Zahlen Dateien: Rational1, RationalApplication RT (ICS @ UIBK) Programmiermethodik 139/613 Objektorientierung Objekte, Klassen und Methoden in Java Konstruktoren • Konstruktor: spezielle Initialisierungsmethode, die bei Erzeugung des Objekts aufgerufen werden • Objektvariablen können darin mit sinnvollen Werten belegt oder initialisiert werden • hat den gleichen Namen wie die Klasse • ist Methode ohne Rückgabetyp • kann Parameter haben RT (ICS @ UIBK) Programmiermethodik 140/613 Objektorientierung Objekte, Klassen und Methoden in Java Konstruktoren und Parameter • Parameterlose Konstruktoren • Form: public Rational (){...} • kann beliebigen Code enthalten • wenn Klasse keinen Konstruktor enthält, fügt Java automatisch einen parameterlosen leeren Konstruktor (Default-Konstruktor) ein • Konstruktoren mit Parametern • Übergabe von Werten (für die Initialisierung) • Beispiele p u b l i c R a t i o n a l ( long n , long d ) { . . . } p u b l i c R a t i o n a l ( long i n t e g e r ) { . . . } RT (ICS @ UIBK) Programmiermethodik 141/613 Objektorientierung Objekte, Klassen und Methoden in Java Konstruktorenverkettung • Mit this () (bzw. this (param1 ,...) ) kann in einem Konstruktor auf andere Konstruktoren zugegriffen werden • Aufruf eines anderen Konstruktors muss erste Anweisung sein • Macht private Konstruktoren sinnvoll: öffentliche Konstrukten nutzen internen (privaten) Konstruktor RT (ICS @ UIBK) Programmiermethodik 142/613 Objektorientierung Objekte, Klassen und Methoden in Java Beispiel: Rationale Zahlen Dateien: Rational2, RationalApplication RT (ICS @ UIBK) Programmiermethodik 143/613 Objektorientierung Objekte, Klassen und Methoden in Java Kopieren von Objekten • Kann mittels Konstruktoren unterstützt werden p u b l i c Account ( S t r i n g name , double amount ) { t h i s . name = name ; // a s u s u a l t h i s . amount = amount ; } p u b l i c Account ( Account o t h e r ) { t h i s . name = o t h e r . name ; // copy c o n s t r u c t o r t h i s . amount = o t h e r . amount ; } • Anwendung Account o r i g , copy ; o r i g = new Account ( " Spengler " , 3 0 0 ) ; copy = new Account ( o r i g ) ; RT (ICS @ UIBK) Programmiermethodik 144/613 Objektorientierung Objekte, Klassen und Methoden in Java Sichtbarkeit von private im Detail • Betrachte Zuweisung this .name = other.name im Kopierkonstruktor • Üblicherweise ist name privates Attribut ⇒ Zugriff this .name sollte erlaubt sein (eigenes Attribut) ⇒ Was ist mit Zugriff other .name ? • 2 Sichtweisen • Objektbasierte Sicht • other ist anderes Objekt derselben Klasse ⇒ erlaube keinen Zugriff • Klassenbasierte Sicht • other ist anderes Objekt derselben Klasse ⇒ erlaube Zugriff • Java nutzt klassenbasierte Sicht RT (ICS @ UIBK) Programmiermethodik 145/613 Objektorientierung Objekte, Klassen und Methoden in Java Probleme beim Kopieren • Objekt kann andere (Daten-)Objekte enthalten (Arrays, Listen, . . . ) • Einfache Wertzuweisung dupliziert nur Referenzen, nicht Datenobjekte • Wird Datenobjekt in Kopie verändert, wirkt sich das auch auf ursprüngliches Objekt aus • Kann manchmal sinnvoll sein • In vielen Fällen wird aber wirkliche Kopie (tiefe Kopie) benötigt RT (ICS @ UIBK) Programmiermethodik 146/613 Objektorientierung Objekte, Klassen und Methoden in Java Flache und tiefe Kopien • Flache Kopie (shallow copy) • Es wird nur mit Wertzuweisung kopiert • Es wird nur das Objekt (nicht die darin enthaltenen Objekte) kopiert • Tiefe Kopie (deep copy) • Es wird auch jedes Objekt kopiert • Wenn das Objekt weitere Objekte enthält, dann wird das Kopieren fortgesetzt (rekursiv weiter) • Original und Kopie enthalten dann logisch gleiche aber getrennte Datenelemente • Bei der Vererbung müssen zusätzliche Aspekte beachtet werden • Java bietet zusätzliche Unterstützungen an (siehe nachfolgendes Kapitel über Vererbung) RT (ICS @ UIBK) Programmiermethodik 147/613 Objektorientierung Objekte, Klassen und Methoden in Java Beispiel: Stack 1 public class Stack { 2 p r i v a t e Account [ ] d a t a ; 3 p r i v a t e i n t pos ; 4 public Stack () { 5 t h i s . d a t a = new Account [ 1 0 0 ] ; 6 t h i s . pos = 0 ; 7 } 8 9 p u b l i c v o i d push ( Account x ) { 10 i f ( t h i s . pos < t h i s . d a t a . l e n g t h ) { 11 t h i s . data [ t h i s . pos ] = x ; 12 t h i s . pos++; 13 } 14 } RT (ICS @ UIBK) Programmiermethodik 148/613 Objektorientierung 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 } Objekte, Klassen und Methoden in Java p u b l i c S t a c k ( S t a c k o t h e r ) { // t o o s h a l l o w t h i s . data = other . data ; t h i s . pos = o t h e r . p o s ; } p u b l i c S t a c k ( S t a c k o t h e r ) { // mixed form t h i s . d a t a = A r r a y s . copyOf ( o t h e r . data , other . data . l e n g t h ) ; t h i s . pos = o t h e r . p o s ; } p u b l i c S t a c k ( S t a c k o t h e r ) { // deep copy t h i s . d a t a = new Account [ o t h e r . d a t a . l e n g t h ] ; f o r ( i n t i =0; i < o t h e r . p o s ; i ++) t h i s . d a t a [ i ] = new Account ( o t h e r . d a t a [ i ] ) ; t h i s . pos = o t h e r . p o s ; } RT (ICS @ UIBK) Programmiermethodik 149/613 Objektorientierung Objekte, Klassen und Methoden in Java Beispiel Aufrufe Account a = new Account ( " Moser " , 1 0 0 0 ) ; S t a c k s 1 = new S t a c k ( ) ; s 1 . push ( a ) ; S t a c k s 2 = new S t a c k ( s 1 ) ; Account a = s 1 . pop ( ) ; Account b = s 2 . pop ( ) ; b . deposit (300); • Unterschiedliche Effekte, abhängig von verwendetem Kopier-Konstruktor (Z. 15, 20 oder 26) RT (ICS @ UIBK) Programmiermethodik 150/613 Objektorientierung Objekte, Klassen und Methoden in Java Klassen und Typen • Klasse legt den Typ für alle Exemplare fest • Typsystem einer Programmiersprache kann diese Information nutzen • Typsysteme • Bestandteil des Compilers einer Programmiersprache oder deren Laufzeitsystems • Überprüft Datentypen zur Übersetzungszeit oder Laufzeit • Jeder Ausdruck hat einen Typ • Typsystem überprüft, ob Verwendung mit Regeln des Typsystems verträglich ist (Ist Operation auf ein Objekt erlaubt?) • Unterscheidung bei Typsystemen • Statisches Typsystem – Überprüfung zur Übersetzungszeit • Dynamisches Typsystem – Überprüfung zur Laufzeit RT (ICS @ UIBK) Programmiermethodik 151/613 Objektorientierung Objekte, Klassen und Methoden in Java Statisches Typsystem • Eigenschaften • Typ von Variablen und Parametern wird im Quelltext deklariert • Schränkt ein, welche Objekte einer Variable zugewiesen werden können • Compiler erkennt frühzeitig unpassende Zuweisung oder unpassenden Aufruf einer Operation • Vorteile • Kompilierte Anwendungen können besser optimiert werden • Programmstruktur ist übersichtlicher • Entwicklungsumgebungen können besser unterstützt werden • Fehler können früher erkannt werden • Beispiele: Java, C++, C# RT (ICS @ UIBK) Programmiermethodik 152/613 Objektorientierung Objekte, Klassen und Methoden in Java Dynamisches Typsystem • Eigenschaften • Variablen sind keinem deklarierten Typ zugeordnet • Variablen können beliebige Objekte referenzieren • Ob Operation auf Objekt erlaubt ist, wird zur Laufzeit überprüft • Vorteile • Flexibilität • Keine Notwendigkeit einer expliziten Typumwandlung • Klassen und Typen sind entkoppelt • Beispiele: Smalltalk, Ruby, Python RT (ICS @ UIBK) Programmiermethodik 153/613 Objektorientierung Objekte, Klassen und Methoden in Java Stark und schwach typisierte Programmiersprachen • stark typisiert: Programmiersprache überwacht das Erstellen und den Zugriff auf alle Objekte so, dass sichergestellt ist, dass Variablen immer auf Objekte verweisen, die auch die Spezifikation des Typs erfüllen, der für die Variablen deklariert ist • schwach typisiert: erlauben es, Objekt einer Variable zuzuweisen, ohne dass Objekt die Spezifikation des Typs der Variable erfüllt • Unterscheidung stark / schwach ist unabhängig von Unterscheidung statisch / dynamisch • Java ist stark typisiert, C ist schwach typisiert (int x = 5.7;) RT (ICS @ UIBK) Programmiermethodik 154/613 Objektorientierung Objekte, Klassen und Methoden in Java Unterschied: Arrays und Klassen Arrays Bestehen aus gleichartigen Elementen Elemente eines Arrays haben keine Namen, werden über Index angesprochen Anzahl der Elemente wird bei Erzeugung festgelegt RT (ICS @ UIBK) Klassen Können aus verschiedenartigen Objektvariablen bestehen Objektvariablen einer Klasse haben Namen und werden über Namen angesprochen Anzahl der Objektvariablen wird bei Deklaration der Klasse festgelegt Programmiermethodik 155/613 Objektorientierung Objekte, Klassen und Methoden in Java Unterschied: statisch / nicht-statisch • Beobachtung: Objektvariablen und Methoden können mit Schlüsselwort static gekennzeichnet werden (voriges Kapitel) oder nicht (dieses Kapitel) • Unterschied? • Klasse ist auch ein Objekt • Klassenobjekt ist eine Schablone, die Aussehen der Klasse festlegt • Sowohl Klassenobjekt als auch “normale” Objekte können Variablen und Methoden haben • Mit static - gehören zum Klassenobjekt (statische Komponenten) • Ohne static - gehören zu den Objekten (objektbezogene Komponenten) • für jede Klasse existiert genau ein Klassenobjekt ⇒ statische Objektvariablen sind wie globale Variablen RT (ICS @ UIBK) Programmiermethodik 156/613 Objektorientierung Objekte, Klassen und Methoden in Java Statische Komponenten (Zugriff) • Zugriff auf Variablen und Methoden • Objektmethoden und Konstruktoren können auf Objekt- und Klassenvariablen (Objekt- und Klassenmethoden) ohne Qualifizierung zugreifen (implizites this .) • Klassenmethoden können ohne Qualifizierung nur auf Klassenvariablen (Klassenmethoden) zugreifen • Zugriff auf Klassenvariablen • Classname. field bzw. Classname.method(...) • Innerhalb Klasse kann Qualifizierung (Classname.) weggelassen werden • Es gibt keine this-Referenz in statischen Methoden • Spezielle Methode main • Jede Klasse, die eine public static void main(String [] args) Methode hat, kann von Kommandozeile wie ein Programm aufgerufen werden (args = Kommandozeilenparameter) RT (ICS @ UIBK) Programmiermethodik 157/613 Objektorientierung Objekte, Klassen und Methoden in Java Beispiel p u b l i c c l a s s Account { private static int counter = 0; p r i v a t e S t r i n g name ; p r i v a t e double amount ; p u b l i c Account ( S t r i n g name , double amount ) { t h i s . name = name ; t h i s . amount = amount ; Account . c o u n t e r ++; // w i t h q u a l i f i e r } public static int getCounter () { // no a c c e s s t o name / amount r e t u r n c o u n t e r ; // w i t h o u t q u a l i f i e r } } RT (ICS @ UIBK) Programmiermethodik 158/613 Objektorientierung Objekte, Klassen und Methoden in Java Beispiel public class AccountClient { p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { Account a = new Account ( " Peter " , 1 0 ) ; Account b = new Account ( " Barbara " , 2 0 ) ; a = new Account ( " Hans " , 5 ) ; System . o u t . p r i n t l n ( Account . g e t C o u n t e r ( ) + " accounts have been created " ) ; } } RT (ICS @ UIBK) Programmiermethodik 159/613 Objektorientierung Objekte, Klassen und Methoden in Java Statische Komponenten - Initialisierung • für Initialisierung kann spezieller Konstruktor verwendet werden (statischer Initialisierer) • hat keinen Namen, keine Parameter p u b l i c c l a s s Account { private static int counter ; static { c o u n t e r = 0 ; // a r b i t r a r y s t m t s ; } ... } • es gibt nur einen einzigen statischen Konstruktor • wird aufgerufen, wenn Klasse geladen wird (Beginn der Programmausführung) RT (ICS @ UIBK) Programmiermethodik 160/613 Objektorientierung Objekte, Klassen und Methoden in Java Unterschied: Objektbezogen oder Statisch Deklarationen existieren Variablen Anlegung Variablen Freigabe Konstruktor Aufruf Variablenzugriff Methodenaufruf RT (ICS @ UIBK) Objektbezogen Statisch ohne static in jedem Objekt wenn Objekt erzeugt wird vom Garage Collector bei Erzeugung des Objekts obj . field this . field obj .method(...) this .method(...) mit static nur einmal pro Klasse wenn Klasse geladen wird bei Programmende wenn Klasse geladen wird Class . field Programmiermethodik Class .method() 161/613 Objektorientierung Objekte, Klassen und Methoden in Java Beziehungen zwischen Klassen • In einem objektorientierten Programm stehen Klassen (und damit Objekte) in Beziehung (selten isolierte Objekte) • Einfaches Beispiel • Klasse Adresse • Klasse Person • Jede Person hat eine Adresse. • Klasse Kurs • Zu einem Kurs können sich mehrere Personen anmelden. • Eine Person leitet den Kurs. RT (ICS @ UIBK) Programmiermethodik 162/613 Objektorientierung Objekte, Klassen und Methoden in Java Kohäsion und Kopplung • Kohäsion • Kohäsion beschreibt wie gut eine Methode tatsächlich genau eine Aufgabe erfüllt oder wie genau abgegrenzt die Funktionalität einer Klasse ist • hohe Kohäsion deutet auf gute Trennung der Zuständigkeiten hin • Genau das will man erreichen, d.h. eine Methode oder Klasse soll nur eine bestimmte Aufgabe erfüllen • Hohe Kohäsion hilft bei Wiederverwendung • Kopplung • Darunter versteht man, wie stark Klassen miteinander in Verbindung stehen • Ziel einer guten Modellierung ist eine möglichst lose Kopplung • Geringe Abhängigkeiten von Klassen untereinander • Gute Datenkapselung und sinnvolle Zugriffsmethoden ermöglichen dies RT (ICS @ UIBK) Programmiermethodik 163/613 Objektorientierung String-Klasse Übersicht Objektorientierung Allgemeine Grundlagen Objekte und Klassen Objekte, Klassen und Methoden in Java String-Klasse Wrapper-Klassen RT (ICS @ UIBK) Programmiermethodik 164/613 Objektorientierung String-Klasse Strings in Java • Die Klasse String ist in Java vordefiniert. • Besonderheiten • Es gibt auch String-Literale: "TestString" • Es gibt einen Operator: + (und auch +=) • Implizite Typkonvertierung • String-Objekte sind nach dem Anlegen nicht mehr veränderbar • Es existieren unterschiedliche Konstruktoren • String s1 = "Hallo"; • String s2 = new String(); • String s3 = new String(s1); • char charArr [] = {’S’,’W’,’E’,’2’}; • String s4 = new String(charArr); • String s5 = new String(charArr ,1,2); RT (ICS @ UIBK) Programmiermethodik 165/613 Objektorientierung String-Klasse Vergleich • Ähnlich wie bei Objekten und Arrays: == ist Referenzvergleich • Beispiele S t r i n g s 1 = " Hallo " ; // " H a l l o " w i r d n u r S t r i n g s 2 = " Hallo " ; // e i n m a l e r z e u g t System . o u t . p r i n t l n ( s 2 == s 1 ) ; // t r u e ! ! ! S t r i n g s 3 = new S t r i n g ( s 1 ) ; System . o u t . p r i n t l n ( s 3 == s 1 ) ; // f a l s e System . o u t . p r i n t l n ( s 1 . e q u a l s ( s 3 ) ) ; // t r u e System . o u t . p r i n t l n ( s 1 . e q u a l s ( " HALLO " ) ) ; // f a l s e System . o u t . p r i n t l n ( s 1 . e q u a l s I g n o r e C a s e ( " HALLO " ) ) ; // t r u e RT (ICS @ UIBK) Programmiermethodik 166/613 Objektorientierung String-Klasse Hilfreiche Methoden public class StringTest { p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { S t r i n g s 1 = "Das ist ein spezieller Test " ; System . o u t . p r i n t l n ( s 1 . l e n g t h ( ) ) ; System . o u t . p r i n t l n ( s 1 . c h a r A t ( 0 ) ) ; System . o u t . p r i n t l n ( s 1 . i n d e x O f ( ’i’ ) ) ; System . o u t . p r i n t l n ( s 1 . l a s t I n d e x O f ( ’i’ ) ) ; System . o u t . p r i n t l n ( s 1 . i n d e x O f ( ’i’ , 5 ) ) ; System . o u t . p r i n t l n ( s 1 . l a s t I n d e x O f ( ’i’ , 1 0 ) ) ; System . o u t . p r i n t l n ( s 1 . i n d e x O f ( "ei" ) ) ; System . o u t . p r i n t l n ( s 1 . s u b s t r i n g ( 8 ) ) ; System . o u t . p r i n t l n ( s 1 . s u b s t r i n g ( 4 , 1 5 ) ) ; } } RT (ICS @ UIBK) Programmiermethodik 167/613 Objektorientierung String-Klasse StringBuilder / StringBuffer • Verhält sich wie String, kann aber editiert werden • String-Objekte sind nach dem Erzeugen nicht mehr veränderbar ⇒ Jede Konkatenation bei Strings erzeugt neue String-Objekte ⇒ Nicht effizient, um große Strings aus vielen kleinen aufzubauen • StringBuilder kann dazu verwendet werden, Zeichenketten aufzubauen • Nach Editieren kann StringBuilder in String umgewandelt werden • Demo: StringTest • Neben append und toString gibt es viele weitere Methoden: • insert ( position , text ), delete ( position , position ), replace ( position , position , text ), charAt( position ), . . . RT (ICS @ UIBK) Programmiermethodik 168/613 Objektorientierung Wrapper-Klassen Übersicht Objektorientierung Allgemeine Grundlagen Objekte und Klassen Objekte, Klassen und Methoden in Java String-Klasse Wrapper-Klassen RT (ICS @ UIBK) Programmiermethodik 169/613 Objektorientierung Wrapper-Klassen Motivation • Zu jedem primitiven Datentyp in Java gibt es eine sogenannte Wrapper-Klasse • Kapselt die primitive Variable in einer objektorientierten Hülle • Methoden für den Zugriff und die Umwandlung • primitiver Datentyp Klasse Byte Short Integer Long Float Double Boolean Character Void RT (ICS @ UIBK) byte short int long float double boolean char void Programmiermethodik 170/613 Objektorientierung Wrapper-Klassen Allgemein • Erzeugung • Konstruktor (primitiver Typ) Integer i = new Integer(10); • Statische Methode (primitiver Typ) Integer i = Integer .valueOf(10); • Konstruktor mit String Integer i = new Integer("-200"); • Rückgabemethoden • Rückgabe als primitiver Typ int j = i. intValue (); • Rückgabe als String String s = i. toString (); • Alle Wrapper-Klassen sind unveränderlich (Wrapper-Klassen sind nur als Ummantelung und nicht als vollständiger Datentyp gedacht) RT (ICS @ UIBK) Programmiermethodik 171/613 Objektorientierung Wrapper-Klassen Nützliches • Wrapper-Klassen bieten nützliche Hilfsmethoden an • Beispiel: Parsen von Strings (z.B. Integer ) • public static int parseInt ( String s) • Versucht einen String in eine Ganzzahl umzuwandeln. • Wenn übergebener String nicht einer Ganzzahl entspricht, wird Programm abgebrochen (Ausnahme) • Konstanten • MIN_VALUE und MAX_VALUE • NEGATIVE_INFINITY, POSITIVE_INFINITY und NaN (bei Float und Double) RT (ICS @ UIBK) Programmiermethodik 172/613 Objektorientierung Wrapper-Klassen Autoboxing / Autounboxing • Automatische Konvertierung zwischen primitiven Datentypen und Wrapper-Klassen (seit Java 1.5) • Compiler fügt notwendigen Code automatisch ein • Zwei Richtungen • Umwandlung primitiver Wert → Wrapper-Objekt • Umwandlung Wrapper-Objekt → primitiver Wert • Ziel • Primitive Typen wie Referenztypen verwenden • Verwendung • Bei Zuweisungen • Bei Methodenaufrufen • Auch innerhalb von Ausdrücken • ++, −−, +=, −= können nicht auf Wrapper-Objekte angewandt werden RT (ICS @ UIBK) Programmiermethodik 173/613 Objektorientierung Wrapper-Klassen Beispiel • ohne Auto(un)boxing Integer i = Integer . valueOf ( 5 ) ; int j = 2 ∗ i . intValue ( ) ; i = Integer . valueOf ( j − 7); • mit Auto(un)boxing I n t e g e r i = 5 ; // a u t o b o x i n g i n t j = 2 ∗ i ; // a u t o u n b o x i n g i = j − 7; // a u t o b o x i n g RT (ICS @ UIBK) Programmiermethodik 174/613 Objektorientierung Wrapper-Klassen Probleme • Autoboxing verschleiert Objektgenerierung! Z. B. Probleme bei == • Integer-Caching und Vergleich • Alle Objekte im Bereich -128 bis +127 werden bereits zur Ladezeit angelegt • Bei einem Boxing in diesem Bereich erhält man immer die gleiche Referenz, ansonsten aber nicht RT (ICS @ UIBK) Programmiermethodik 175/613 Objektorientierung Wrapper-Klassen Probleme: Beispiele Integer j1 = 2; Integer j2 = 2; System . o u t . p r i n t l n ( j 1 == j 2 ) ; // I n t e g e r l1 = 128; I n t e g e r l2 = 128; System . o u t . p r i n t l n ( l 1 == l 2 ) ; // I n t e g e r n1 = new I n t e g e r ( 1 0 ) ; I n t e g e r n2 = I n t e g e r . v a l u e O f ( 1 0 ) ; I n t e g e r n3 = 1 0 ; I n t e g e r n4 = 1 0 ; System . o u t . p r i n t l n ( n1 == n2 ) ; // System . o u t . p r i n t l n ( n2 == n3 ) ; // System . o u t . p r i n t l n ( n1 == n3 ) ; // System . o u t . p r i n t l n ( n3 == n4 ) ; // RT (ICS @ UIBK) Programmiermethodik true false false true false true 176/613 Objektorientierung Wrapper-Klassen Weitere Probleme • Keine Konvertierung von null zu 0 Integer i = null; int n = i; // java . lang . NullPointerException (NullPointerException wird immer dann geworfen, wenn versucht wird, auf Objektmethoden oder Objektvariablen von null zuzugreifen, hier: null . intValue) • Keine implizite Typkonvertierung float fa Float fb Float fc Integer RT (ICS @ UIBK) = = = [] 123; 123; 123 f ; iarr = // okay // e r r o r // okay new i n t [ ] { 1 , 2 , 3 , 4 } ; // e r r o r Programmiermethodik 177/613 Vererbung und Polymorphismus Übersicht Vererbung und Polymorphismus Vererbung Allgemein Vererbung der Spezifikation in Java Vererbung der Implementierung in Java Abstrakte Klassen Die Klasse Object RT (ICS @ UIBK) Programmiermethodik 178/613 Vererbung und Polymorphismus Vererbung Allgemein Übersicht Vererbung und Polymorphismus Vererbung Allgemein Vererbung der Spezifikation in Java Vererbung der Implementierung in Java Abstrakte Klassen Die Klasse Object RT (ICS @ UIBK) Programmiermethodik 179/613 Vererbung und Polymorphismus Vererbung Allgemein Vererbung Allgemein • Klassen modellieren Dinge der realen Welt • Dinge kommen in verschiedenen Varianten vor, die man durch Klassifikation hierarchisch gliedern kann • Programme sollten • mit den verschiedenen Varianten arbeiten und • in bestimmten Situationen Varianten nicht unbedingt unterscheiden (gleich behandeln) • Java bietet die Möglichkeit • hierarchische Klassenstrukturen zu bilden und • Varianten von Objekten gleich zu behandeln RT (ICS @ UIBK) Programmiermethodik 180/613 Vererbung und Polymorphismus Vererbung Allgemein Unterklassen und Oberklassen • Klasse S ist eine Unterklasse der Klasse A, wenn S Spezifikation von A erfüllt, umgekehrt aber A nicht die Spezifikation von S (A ist eine Oberklasse von S) • Beziehung zwischen A und S wird Spezialisierung genannt • Beziehung zwischen S und A wird Generalisierung genannt • [Lahres 2006] RT (ICS @ UIBK) Programmiermethodik 181/613 Vererbung und Polymorphismus Vererbung Allgemein Prinzip der Ersetzbarkeit • Wenn Klasse B eine Unterklasse der Klasse A ist, dann können in einem Programm alle Exemplare der Klasse A durch Exemplare der Klasse B ersetzt werden und es gelten weiterhin alle zugesicherten Eigenschaften der Klasse A • Exemplare der Unterklasse sind gleichzeitig Exemplare der Oberklasse in Bezug auf die der Oberklasse zugrunde liegende Spezifikation • Vorbedingungen, Nachbedingungen und Invarianten gelten auch dann, wenn Exemplare der Oberklasse durch Exemplare der Unterklasse ersetzt werden • Beispiele folgen noch RT (ICS @ UIBK) Programmiermethodik 182/613 Vererbung und Polymorphismus Vererbung Allgemein Kategorien von Klassen • Klassen können kategorisiert werden • abhängig davon in welchem Umfang sie selbst für die von ihnen spezifizierte Schnittstelle auch Methoden anbieten • Kategorien • Konkrete Klassen • Rein spezifizierende Klassen (Schnittstellen-Klassen) • Abstrakte Klassen • [Lahres 2006] RT (ICS @ UIBK) Programmiermethodik 183/613 Vererbung und Polymorphismus Vererbung Allgemein Konkrete Klassen • Stellen für alle von der Klasse spezifizierte Operationen auch Methoden bereit • Es können Exemplare erzeugt werden • Wurden bisher in dieser Vorlesung besprochen • Beispiel: Array-basierter Stack public class ArrayStack { private Object [ ] elements ; private int s i z e ; p u b l i c v o i d push ( O b j e c t o b j ) { elements [ s i z e ] = obj ; s i z e ++; } p u b l i c O b j e c t pop ( ) { . . . } ... } RT (ICS @ UIBK) Programmiermethodik 184/613 Vererbung und Polymorphismus Vererbung Allgemein Schnittstellen-Klassen • Schnittstellen-Klassen • Dienen alleine der Spezifikation einer Menge von Operationen • Für keine Operation wird Implementierung bereitgestellt • Es können keine Exemplare erzeugt werden • Implementieren • Wenn eine Unterklasse einer Schnittstellen-Klasse Methoden für alle von der Schnittstelle spezifizierten Operationen bereitstellt • Unterklasse implementiert die Schnittstelle • Einsatz bei statisch typisierten Programmiersprachen (wie Java) • Beispiel public interface Stack { // no i m p l e m e n t a t i o n s ! ! v o i d push ( O b j e c t o b j ) ; // p u t o b j on s t a c k O b j e c t pop ( ) ; // r e t u r n and remove t o p e l e m e n t O b j e c t p e e k ( ) ; // r e t u r n t o p e l e m e n t ( no r e m o v a l ) boolean i s E m p t y ( ) ; // c h e c k i f s t a c k i s empty } RT (ICS @ UIBK) Programmiermethodik 185/613 Vererbung und Polymorphismus Vererbung Allgemein Abstrakte Klassen • Abstrakte Klassen • Stellen meist für mindestens eine Operation keine Implementierung bereit (Spezialfall: Alle Methoden implementiert, Klasse aber als abstrakt markiert, siehe Abschnitt über abstrakte Klassen) • keine direkten Exemplare möglich (Java: kein new AbstractClass (...) ) • Alle Exemplare einer abstrakten Klasse müssen gleichzeitig Exemplare einer nicht abstrakten Unterklasse sein • Abstrakte Methoden • Erlauben eine Operation für eine Klasse zu definieren, ohne dafür eine Methodenimplementierung zur Verfügung zu stellen • Methode dient nur zur Spezifikation • Implementierung erfolgt in abgeleiteter konkreter Unterklasse RT (ICS @ UIBK) Programmiermethodik 186/613 Vererbung und Polymorphismus Vererbung Allgemein Beispiel p u b l i c a b s t r a c t c l a s s D e f a u l t S t a c k implements S t a c k { // p r o v i d e d e f a u l t i m p l e m e n t a t i o n f o r p e e k public Object peek ( ) { O b j e c t o = t h i s . pop ( ) ; t h i s . push ( o ) ; return o ; } // l e a v e r e m a i n i n g s t a c k o p e r a t i o n s open // f o r c o n c r e t e c l a s s e s p u b l i c a b s t r a c t O b j e c t pop ( ) ; p u b l i c a b s t r a c t boolean i s E m p t y ( ) ; p u b l i c a b s t r a c t v o i d push ( O b j e c t o b j ) ; } RT (ICS @ UIBK) Programmiermethodik 187/613 Vererbung und Polymorphismus Vererbung Allgemein Polymorphismus • Polymorph = vielgestaltig • Variable oder Methode kann gleichzeitig mehrere Typen haben • Objektorientierte Sprachen sind polymorph (Konventionelle Sprachen wie zum Beispiel Pascal sind monomorph) • Verschiedene Arten: • Universeller Polymorphismus • Parametrischer Polymorphismus • Inklusions-, Vererbungspolymorphismus • Ad-hoc Polymorphismus • Überladen • Typumwandlung RT (ICS @ UIBK) Programmiermethodik 188/613 Vererbung und Polymorphismus Vererbung Allgemein Polymorphismus Arten • Universeller Polymorphismus • Name oder Wert kann theoretisch unendlich viele Typen besitzen • Implementierung einer universell polymorphen Operation führt generell gleichen Code unabhängig von den Typen ihrer Argumente aus • Ad-hoc-Polymorphismus • Name oder ein Wert kann nur endlich viele verschiedene Typen besitzen • Typen sind zur Übersetzungszeit bekannt • Ad-hoc-polymorphe (also überladene) Operationen können abhängig von den Typen ihrer Argumente unterschiedlich implementiert sein RT (ICS @ UIBK) Programmiermethodik 189/613 Vererbung und Polymorphismus Vererbung Allgemein Polymorphismus in dieser Vorlesung • Ad-hoc Polymorphismus wurde schon behandelt (Typumwandlung, Überladen) • Universeller Polymorphismus • Parametrischer Polymorphismus wird noch behandelt (Generische Programmierung) • Inklusionspolymorphismus ist zentrales Thema dieses Kapitels • Inklusionspolymorphismus • Ersetzbarkeitsprinzip • Dynamische Polymorphie RT (ICS @ UIBK) Programmiermethodik 190/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Übersicht Vererbung und Polymorphismus Vererbung Allgemein Vererbung der Spezifikation in Java Vererbung der Implementierung in Java Abstrakte Klassen Die Klasse Object RT (ICS @ UIBK) Programmiermethodik 191/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Interfaces • Interfaces bestehen aus • Methoden-Spezifikation ohne Rumpf • Sind abstrakte Methoden • Sind immer public • Keine Konstruktoren • Konstanten • Alle Objektvariablen sind public static final (nur Konstanten) • Implementierung • Eine Klasse kann ein Interface implementieren RT (ICS @ UIBK) Programmiermethodik 192/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Schlüsselwort final • verschiedenen Dinge können als final gekennzeichnet werden • Klassenvariablen • Objektvariablen • lokale Variablen • Methodenparameter • Methoden und Klassen (später) • Bedeutung • finale Variable oder Parameter kann nur maximal einmal einen Wert zugewiesen bekommen, danach besteht nur noch Lesezugriff • bei Klassenvariablen, Objektvariablen und Parametern, geschieht dies genau einmal • Klassenvariablen: bei Deklaration oder im statischen Initialisierungsblock • Objektvariablen: bei Deklaration oder im Konstruktor • Parameter: beim Aufruf der Methode • Achtung bei Variablen von Referenztypen: Referenz bleibt unverändert, aber Objekt kann sich ändern RT (ICS @ UIBK) Programmiermethodik 193/613 Vererbung und Polymorphismus c l a s s Test { final int x ; final int y = 5; int z ; s t a t i c f i n a l i n t PI ; static { i n t x = 7 ; PI = x ∗ x ; } T e s t ( f i n a l Account b , i n t v ) { v += 3 + PI ; b . d e p o s i t ( 3 0 0 ) ; // okay b = n u l l ; // n o t okay t h i s . y = 3 ; // n o t okay } // n o t okay Test ( ) { this ( null , 3); t h i s . x = 2 ; // n o t okay } RT }(ICS @ UIBK) Programmiermethodik Vererbung der Spezifikation in Java 194/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Klassen und Interfaces • Klassen implementieren Interfaces (mit implements) • Man kann keine Objekte von Interfaces anlegen • Klasse kann mehrere Interfaces implementieren • Interface kann von mehreren Klassen implementiert werden • Implementierung eines Interfaces muss die Spezifikation erfüllen • Alle Methoden müssen implementiert werden (Ausnahmen: später) • Konstruktoren müssen in den Klassen implementiert werden (nicht im Interface) RT (ICS @ UIBK) Programmiermethodik 195/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Beispiel (Komplexe Zahlen) • Einfaches Interface für komplexe Zahlen p u b l i c i n t e r f a c e Complex { double g e t R e a l ( ) ; double g e t I m a g ( ) ; double g e t D i s t a n c e ( ) ; double g e t P h a s e ( ) ; } • Alle Methoden sind implizit public und abstract (Könnte man angeben, muss man aber nicht) • Jede Klasse, die Interface implementiert, muss die 4 Methoden implementieren • Beispiel: Siehe Polar.java, Cartesian.java, Complex.java RT (ICS @ UIBK) Programmiermethodik 196/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Erläuterungen • Klasse Cartesian und Polar implementieren das Interface Complex • Beide Klassen implementieren die vorgegebenen Methoden (jeweils unterschiedlich) • Beide Klassen geben zusätzlich einen Konstruktor an • Form des Konstruktors wird nicht vom Interface vorgegeben • Es könnten noch mehrere Konstruktoren angegeben werden • Es können zusätzliche Methoden angegeben werden (add, sub etc.) ⇒ keine Einschränkung für weitere Methoden • Beide Klassen sind gleichberechtigte und unabhängige Implementierungen von Complex RT (ICS @ UIBK) Programmiermethodik 197/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Polymorphismus • Interfaces definieren einen Typ • Können in Variablendeklarationen, Parameterlisten, und als Ergebnistyp von Methoden verwendet werden • Bsp: other und Rückgabe Wert in multiply sind vom Typ Complex • Warum funktioniert das Beispiel? • Wenn Klasse das Interface Complex implementiert, können Objekte dieser Klasse einer Variable vom Typ Complex zugewiesen werden • Variable other kann daher auf unterschiedliche Objekte zeigen ⇒ Inklusionspolymorphismus RT (ICS @ UIBK) Programmiermethodik 198/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Inklusionspolymorphismus • Variable können Objekte unterschiedlichen Typs zugeordnet werden • Typ der Variable beschreibt nur Schnittstelle • Objekte sind zuweisungs-kompatibel, wenn Klasse Schnittstelle erfüllt • Beim Aufruf einer Operation wird entsprechende Methode ausgewählt (zur Laufzeit, abhängig vom Objekt) • Späte Bindung (dynamisches Binden) • Im Hauptprogramm wird zufällig eine Implementierung ausgewählt • Frage: Wie wird richtige Methode gefunden? • Zur Laufzeit wird von der JVM abhängig vom momentan zugewiesenen Objekt die entsprechende Methode aufgerufen – dynamisches Binden • Methodenaufruf wird abhängig vom Kontext in unterschiedliche Abläufe umgesetzt • Beispiel Complex c1 = new P o l a r ( 2 , 0 ) ; Complex c2 = new C a r t e s i a n ( 0 , 1 ) ; c1 . m u l t i p l y ( c2 ) ; c2 . m u l t i p l y ( c1 ) ; c1 . m u l t i p l y ( c1 ) ; RT (ICS @ UIBK) Programmiermethodik 199/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Statischer / Dynamischer Typ • Statischer Typ • Typ der Variable laut Deklaration • Bestimmt, welche Objektvariablen und Methoden angesprochen werden können • Kompatibilitätsüberprüfung • Dynamischer Typ • Typ zur Laufzeit (abhängig vom tatsächlich zugewiesenen Objekt) • Kann sich nach jeder (gültigen) Zuweisung ändern • Bestimmt, welche Methoden wirklich aufgerufen werden • Beispiel Complex c = new P o l a r ( 2 , 0 ) ; c = new C a r t e s i a n ( 2 , 0 ) ; c = Math . random ( ) > 0 . 5 ? c : new P o l a r ( 1 , 1 ) ; c = c . multiply (c ); RT (ICS @ UIBK) Programmiermethodik 200/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Mehrfache Implementierung • Klasse kann mehrere Interfaces implementieren (muss alle Methoden dieser Interfaces implementieren) • Interfaces können die gleiche Methode vorschreiben (gleiche Signatur) • Klasse, die diese Interfaces implementiert, muss Methode nur einmal implementieren RT (ICS @ UIBK) Programmiermethodik 201/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Beispiel public interface P r in t a bl e { String toString (); } p u b l i c c l a s s C a r t e s i a n implements Complex , P r i n t a b l e { // methods f o r i n t e r f a c e Complex a s b e f o r e public String toString () { r e t u r n ( t h i s . r e a l + " + " + t h i s . imag + "i" ) ; } } RT (ICS @ UIBK) Programmiermethodik 202/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Beispiel • Beispiel: Siehe Stack.java, Container.java, Iterator.java, ArrayStack.java, StackContainerTest.java RT (ICS @ UIBK) Programmiermethodik 203/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Ableiten (bei Interfaces) • Interface kann von anderen Interface abgeleitet werden • Verwende dazu Schlüsselwort extends • Interface kann mehrere Super-Interfaces haben • Interface übernimmt alles aus den Super-Interfaces und kann zusätzliche Methoden und Konstanten hinzugeben • jeder Variablen eines Super-Interface kann Objekt vom Typ des Sub-Interfaces zugewiesen werden RT (ICS @ UIBK) Programmiermethodik 204/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Beispiel public interface I t e r a t o r { boolean h a s N e x t ( ) ; // i s t h e r e n e x t e l e m e n t S t r i n g n e x t ( ) ; // g i v e me n e x t e l e m e n t } p u b l i c i n t e r f a c e R e m o v a b l e I t e r a t o r extends I t e r a t o r { v o i d remove ( ) ; // remove l a s t e l e m e n t t h a t was r e t u r n e d by n e x t ( ) // from c o n t a i n e r // a u t o m a t i c a l l y i n h e r i t s methods from I t e r a t o r } • siehe auch LinkedList.java RT (ICS @ UIBK) Programmiermethodik 205/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Konstanten • In Interfaces können Konstanten deklariert werden • Konstanten können auch weitervererbt werden • Wenn Klasse Interface mit Konstanten implementiert, dann übernimmt sie diese Konstanten! • Wird normalerweise nicht empfohlen! ⇒ Sollte in einer sauberen Implementierung vermieden werden! RT (ICS @ UIBK) Programmiermethodik 206/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Beispiel (schlecht) public interface Grundfarben { i n t ROT = 1 , GRUEN = 2 , BLAU = 3 ; } p u b l i c i n t e r f a c e S o c k e n f a r b e n extends G r u n d f a r b e n { i n t SCHWARZ = 1 0 , LILA = 1 1 ; } p u b l i c i n t e r f a c e H o s e n f a r b e n extends G r u n d f a r b e n { i n t LILA = 1 1 , SCHWARZ = 2 0 , BRAUN = 2 1 ; } p u b l i c i n t e r f a c e A l l e f a r b e n extends S o c k e n f a r b e n , H o s e n f a r b i n t BRAUN = 3 0 ; } p u b l i c c l a s s A implements A l l e f a r b e n { } public class InterfaceTest { p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { System . o u t . p r i n t l n ( S o c k e n f a r b e n .ROT ) ; // s c h l e c h t System . o u t . p r i n t l n ( A l l e f a r b e n .ROT ) ; // s c h l e c h t System . o u t . p r i n t l n ( H o s e n f a r b e n .SCHWARZ ) ; // System . o u t . p r i n t l n ( A l l e f a r b e n .SCHWARZ ) ; g e h t n i c h t // System . o u t . p r i n t l n ( A l l e f a r b e n . LILA ) ; geht n i c h t System . o u t . p r i n t l n ( new A ( ) . ROT ) ; // s c h l e c h t System . o u t . p r i n t l n (A .ROT ) ; // s c h l e c h t }} RT (ICS @ UIBK) Programmiermethodik 207/613 Vererbung und Polymorphismus Vererbung der Spezifikation in Java Einsatz von Interfaces • Erlauben isolierte Entwicklung von Implementierungen • Anwendungen können nur auf Interfaces aufbauen • Anwendung deklariert Variablen vom Interface-Typ • Zukünftige Klassen, die Interface implementieren, können sofort in die Anwendung eingebunden werden • Leere Interfaces • Marker-Interfaces (werden noch besprochen) RT (ICS @ UIBK) Programmiermethodik 208/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Übersicht Vererbung und Polymorphismus Vererbung Allgemein Vererbung der Spezifikation in Java Vererbung der Implementierung in Java Abstrakte Klassen Die Klasse Object RT (ICS @ UIBK) Programmiermethodik 209/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Vererbung und Interfaces • Interface fixiert gemeinsame Eigenschaften von Klassen • Klassen erfüllen gleichen Zweck (im Interface angegeben) • Sind ansonsten unabhängig • Bei vielen Klassen beruht Verwandtschaft nicht nur auf gleichen Eigenschaften, sondern auf Erweiterung und Modifikation von Eigenschaften RT (ICS @ UIBK) Programmiermethodik 210/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Vererbung der Implementierung (allgemein) • Unterklassen erben in Oberklassen implementierte Funktionalität • Unterklassen erben • Verpflichtungen • Alle Methoden • Alle Daten (abhängig von Sichtbarkeits-Modifikatoren) • Funktionalität kann komplett übernommen werden oder von der Unterklasse verändert/erweitert werden ⇒ Überschreiben RT (ICS @ UIBK) Programmiermethodik 211/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Überschreiben (allgemein) • Unterklasse implementiert Operation, für die es Methode in Oberklasse gibt • Wird Methode auf Exemplar der Unterklasse aufgerufen, wird überschriebene Implementierung aufgerufen • Hängt nicht vom Typ der Variable ab, über die das Objekt referenziert wird • Entscheidend ist Typ des Objekts ⇒ Polymorphie! • Überschriebene Methode kann • eigene Implementierung haben und • zusätzlich auf geerbte Implementierung zugreifen RT (ICS @ UIBK) Programmiermethodik 212/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Überschreiben (speziell) • Geschützte Methoden (protected) • Gehören nicht zur Schnittstelle • Unterstützen Methoden zur Bereitstellung der Schnittstelle • Können in Unterklassen verwendet und überschrieben werden • Überschreiben verhindern • Oberklasse will bestimmte Funktionalität erzwingen • Unterklasse darf nicht überschreiben (z.B. um bestimmte Verträge einzuhalten) RT (ICS @ UIBK) Programmiermethodik 213/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Beispiel (Fahrzeugverwaltung, minimal) • KFZ • Kennzeichen • Standort • Methode zur Ausgabe der KFZ-Daten • LKW • Kennzeichen • Standort • Ladung • Methode zur Ausgabe der KFZ-Daten • Methode zum Ändern der Ladung RT (ICS @ UIBK) Programmiermethodik 214/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Beispiel (Vererbungshierarchie) • Auf Typebene (Ober- und Unterklassen) • Auf Instanzebene (Mengen-Beziehung) RT (ICS @ UIBK) Programmiermethodik 215/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Beispiel (schlechte Lösung) • Vehicle1.java, Truck1.java, VehicleTest1.java RT (ICS @ UIBK) Programmiermethodik 216/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Vererbung in Java • Klasse B kann die Subklasse (Unterklasse, abgeleitete Klasse) einer Klasse A (Superklasse, Oberklasse, Basisklasse) sein • Subklasse erbt alle Objektvariablen und Methoden der Superklasse • Subklasse kann weitere Objektvariablen deklarieren und Methoden implementieren • Objekt der Subklasse ist auch Objekt der Superklasse • Java unterstützt nur Einfachvererbung (nur eine Superklasse) RT (ICS @ UIBK) Programmiermethodik 217/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Beispiel (mit Vererbung) • Vehicle2.java, Truck2.java, VehicleTest2.java RT (ICS @ UIBK) Programmiermethodik 218/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Syntax • Zusatz extends Vehicle2 lässt Klasse Truck2 von Klasse Vehicle2 erben • Bestandteile von Klasse Vehicle2 werden in Klasse Truck2 eingeblendet (sind dort vorhanden) • Aber nicht alles ist sichtbar (z.B. number, location sind als private deklariert)! • Methode getInfo wird geerbt und kann in der Klasse Truck2 aufgerufen werden RT (ICS @ UIBK) Programmiermethodik 219/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Konstruktoren bei der Vererbung • Konstruktoren werden nicht vererbt • Jeder Konstruktor einer Subklasse muss zuerst einen Superklassen-Konstruktor aufrufen (Initialisierung der Superklasse)! • Aufruf: super (...); • Ausnahme: zuerst anderen Konstruktor mit this (...); aufrufen • Wenn nichts angegeben wird (kein super (...); oder this (...); ), dann ruft Konstruktor den Default-Konstruktor der Superklasse auf • Wenn dieser nicht existiert? • entweder in Superklasse implementieren oder • anderen Konstruktor in Superklasse explizit aufrufen RT (ICS @ UIBK) Programmiermethodik 220/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Expliziter Aufruf • Default-Konstruktor kann auch explizit mit super(); aufgerufen werden (redundant) • Wie bei this () und seinen Varianten kann man auch bei super() zu allen möglichen Konstruktoren eine Verbindung herstellen • Im Beispiel wird mit super(number,location); der entsprechende Konstruktor in Vehicle2 aufgerufen • Folgende Einschränkungen existieren • super-Aufruf darf nur einmal vorkommen • super-Aufruf muss als erste Anweisung auftreten • this-Aufrufe und super-Aufrufe können nicht gleichzeitig verwendet werden (immer erster Aufruf) RT (ICS @ UIBK) Programmiermethodik 221/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Zugriffsschutz mit protected • Im Beispiel sind number und location mit private gekennzeichnet • In Truck2 kann man nicht darauf zugreifen • Wenn man aber einen Zugriff haben will? • Mit protected markierte Objektvariablen und Methoden stehen allen Subklassen zur Verfügung • Sind in den Subklassen sichtbar • Sichtbarkeit erstreckt sich auch über mehrere Stufen einer Vererbungshierarchie • Wie bei private gibt es eine Unterscheidung zwischen klassenbasierter und objektbasierter Definition (in Java klassenbasiert) • Sichtbarkeitsregeln können auch bei Klassen verwendet werden (Beispiele später) RT (ICS @ UIBK) Programmiermethodik 222/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Überschreiben von Methoden • Klasse kann Methoden, die sie von Superklasse erbt, neu implementieren (überschreiben) • Folgende Regeln gelten dabei • Name und Parameterliste der überschriebenen Methode müssen exakt übernommen werden • Ansonsten: Überladen (auch in Subklassen möglich) • Zugriffsschutz darf gelockert werden (z.B. protected in public) • Ergebnistyp darf vom Ergebnistyp der zu überschreibenden Methode abgeleitet werden • Rumpf kann komplett ersetzt werden RT (ICS @ UIBK) Programmiermethodik 223/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Beispiele • Zugriff mittels protected Attributen: Vehicle3.java, Truck3.java, VehicleTest3.java • bessere Lösung mit Zugriff mittels protected Gettern: Vehicle4.java, Truck4.java, VehicleTest4.java RT (ICS @ UIBK) Programmiermethodik 224/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Zugriff auf die Superklasse • super kann auch in normalen Methoden eingesetzt werden • super.method(...) ruft die entsprechende Methode method(...) in direkten Superklasse auf • Weitere Verkettung ist nicht möglich! ⇒ super.super.method(...) ist nicht möglich • method(...) darf nicht private sein • Kann auch bei Objektvariablen eingesetzt werden RT (ICS @ UIBK) Programmiermethodik 225/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Beispiele • noch bessere Lösung mittels super: Vehicle5.java, Truck5.java, VehicleTest5.java RT (ICS @ UIBK) Programmiermethodik 226/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Polymorphismus (Wiederholung) • Es ist erlaubt, dass Variable objA vom Typ A Objekt objB einer Subklasse B zugewiesen werden darf • objA = objB; ist immer erlaubt (Ersetzbarkeitsprinzip) • objB = (B) objA; ist nur zulässig, wenn objA auf B-Objekt zeigt • Expliziter Cast notwendig • Wird als Downcast bezeichnet • Downcast ist problematisch • Verletzt Prinzip der Trennung der Schnittstelle von Implementierung • Kann meist mit Hilfe dynamischer Polymorphie und Prinzip der Ersetzbarkeit umgangen werden RT (ICS @ UIBK) Programmiermethodik 227/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java instanceof Operator • Objektvariablen sind polymorph • sie haben statischen Typ (Deklaration) • sie haben aktuelle Klassenzugehörigkeit (dynamischer Typ) • dynamischer Typ kann mit instanceof abgefragt werden • Vererbung muss aber berücksichtigt werden • Erbt Klasse B von Klasse A, dann ist Exemplar der Klasse B auch Exemplar der Klasse A, Umkehrung gilt nicht • instanceof sollte nur in Ausnahmefällen eingesetzt werden RT (ICS @ UIBK) Programmiermethodik 228/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Beispiel • VehicleTest5b.java RT (ICS @ UIBK) Programmiermethodik 229/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Dynamisches Binden • Beim Übersetzen von Methodenaufrufen prüft Compiler statischen Typ des Zielobjekts • Variable v in typeTest(Vehicle5 v) hat Typ Vehicle • Klasse Vehicle5 definiert Methode getInfo () und daher wird Aufruf akzeptiert • Zur Laufzeit wird Methodenaufruf dynamisch gebunden • Aktueller Typ von v wird herangezogen, um tatsächliche Methode zu bestimmen • Wenn Methode nicht überschrieben wurde, wird entsprechende Methode aus Superklasse aufgerufen • Beispiel: typeTest(new Truck5(...)) wird getInfo () aus Truck5 ausführen RT (ICS @ UIBK) Programmiermethodik 230/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Statisches Binden • In bestimmten Situationen werden Methoden statisch (und nicht dynamisch) gebunden • Statische Methoden • Gehören zu Klasse und nicht zu Objekt • Konstruktoren • Objekt muss erst vom Konstruktor erzeugt werden • Private Methoden • Sind in Subklasse nicht sichtbar • Neue Definition einer privaten Methode ist keine Redefinition • Binden von Datenelementen • Datenelemente werden statisch gebunden • Beim Zugriff wird der statische Typ herangezogen • Datenelemente werden aber geerbt RT (ICS @ UIBK) Programmiermethodik 231/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Beispiel public class protected } public class protected } public class } Base { int data = 1; Sub extends Base { int data = 2; Sub2 extends Sub { public c l a s s Test { p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { Base x = new Sub ( ) ; Sub2 s = new Sub2 ( ) ; System . o u t . p r i n t l n ( x . d a t a ) ; System . o u t . p r i n t l n ( s . d a t a ) ; } } RT (ICS @ UIBK) Programmiermethodik 232/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java final bei Methoden und Klassen • final als Attribut bei Methode • Methode kann in Subklasse nicht überschrieben werden • dynamisches Binden wird unterbunden • final als Attribut bei Klasse • es kann keine Subklasse gebildet werden • alle Methoden sind automatisch final • Beispiele: String, StringBuilder RT (ICS @ UIBK) Programmiermethodik 233/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Kovarianz, Kontravarianz, Invarianz • Fragestellung: Was darf beim Überschreiben verändert werden? • Kovarianz • Redefinition von Parameter- und Ergebnistypen mit Subtypen • Kontravarianz • Redefinition von Parameter- und Ergebnistypen mit Supertypen • Invarianz • Typen bleiben gleich • Java (seit Version 1.5) • Kovarianz bei Ergebnistypen • Sonst Invarianz RT (ICS @ UIBK) Programmiermethodik 234/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Kovarianter Ergebnistyp • Kovariante Ergebnistypen erlauben kompatiblen Ergebnistyp beim Überschreiben von Methoden und bei Implementierung von Interfacemethoden • Beispiele • Interface: iterator () in LinkedList liefert RemovableIterator, während iterator () in Interface Container Rückgabetyp Iterator hat • Überschreiben: class A { p u b l i c A getCopy ( ) { . . . } } c l a s s B extends A { p u b l i c B getCopy ( ) { . . . } } RT (ICS @ UIBK) Programmiermethodik 235/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Vererbung der Implementierung und Redundanzen • Vorteil der Vererbung der Implementierung • Methoden müssen nicht neu implementiert werden • Redundanzen im Quellcode werden vermieden • Aber • Vererbung legt starre Struktur fest • Erweiterungen sind mit Aufwand verbunden RT (ICS @ UIBK) Programmiermethodik 236/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Probleme • Klasse B kann Funktionalität der Klasse A nutzen durch • Vererbung (B erbt von A) • Beziehung (Assoziation zwischen B und A, B benutzt A) • Falle • Vererbung erscheint einfacher • Aber nicht immer sinnvoll • Prinzip der Ersetzbarkeit sollte immer gelten RT (ICS @ UIBK) Programmiermethodik 237/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Ersetzbarkeitsprinzip - Bedingungen • Unterklasse kann Vorbedingungen für Operation, die in Oberklasse definiert werden, einhalten oder abschwächen, aber nicht verschärfen • Unterklasse kann Nachbedingungen für Operation, die in Oberklasse definiert werden, einhalten oder erweitern, aber nicht einschränken • Unterklasse muss dafür sorgen, dass für Oberklasse definierten Invarianten immer gelten • Verhaltensänderung ist aber erlaubt! RT (ICS @ UIBK) Programmiermethodik 238/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Beispiel: Einhaltung des Ersetzbarkeitprinzips • Container bietet Einfügen und Iterator an • Bedingungen: Iterator muss über alle Elemente iterieren, die bislang eingefügt (und nicht entfernt) wurden • Klasse Tree implementiert Container-Schnittstelle • unbalanciert • preorder-Iterator • Klasse BalancedTree erbt von Tree • neue Zusatzeigenschaft: Einfügen in logarithmischer Zeit • Verhaltensänderung bei Iterator RT (ICS @ UIBK) Programmiermethodik 239/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Beispiel: Verletzung des Prinzips der Ersetzbarkeit public class Rectangle { double w i d t h ; double h e i g h t ; p u b l i c v o i d s c a l e W i d t h ( double f a c t o r ) { . . . } p u b l i c v o i d s c a l e H e i g h t ( double f a c t o r ) { . . . } p u b l i c v o i d s c a l e ( double f a c t o r ) { . . . } ... } p u b l i c c l a s s S q u a r e extends R e c t a n g l e { // i n v a r i a n t : w i d t h = h e i g h t } • Problem: Quadrat kann nicht wie Rechteck benutzt werden • Beispiel: R e c t a n g l e r = new S q u a r e ( 5 . 0 ) ; r . scaleWidth (2); RT (ICS @ UIBK) Programmiermethodik 240/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Problem der instabilen Basisklasse • Falls das Prinzip der Ersetzbarkeit gilt? • Alles ok? • Gilt das auch in Zukunft? • Problem der instabilen Basisklasse (Fragile Base Class Problem) • Anpassungen an Basisklasse können zu unerwartetem Verhalten von abgeleiteten Klassen führen ⇒ Wartung von Systemen, die nur Vererbung der Implementierung benutzen, ist schwierig • Sind spätere Änderungen an der Basisklasse sehr wahrscheinlich: • Vererbung der Spezifikation (und nicht der Implementierung) • Wenn man Redundanzen vermeiden möchte - Delegation RT (ICS @ UIBK) Programmiermethodik 241/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Delegation • Objekt setzt Operation so um, dass Aufruf der Operation an anderes Objekt delegiert (weitergereicht) wird • Verantwortung, Implementierung für bestimmte Schnittstelle bereitzustellen, wird an Exemplar einer anderen Klasse delegiert • Vorteil • Kann mit Vererbung der Spezifikation gemeinsam benutzt werden (Quellcode einsparen) • Auch ohne Mehrfachvererbung kann Funktionalität von mehreren Klassen benutzt werden • Dynamisch (Delegat kann zur Laufzeit geändert werden) • Beispiel: Well.java, WellTest.java, . . . RT (ICS @ UIBK) Programmiermethodik 242/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java ”is-a” vs. ”has-a” • ”B ist ein A” ⇒ B wird von A abgeleitet • ”B enthält ein A” ⇒ B definiert Objektvariable vom Typ A • Beispiel • 2 Klassen Dreieck und Punkt • Dreieck ist ein Punkt – Falsch • Dreieck enthält einen Punkt – Richtig ⇒ Klasse Dreieck verwendet Klasse Punkt (Objektvariable vom Typ Punkt) • 2 Klassen Dreieck und Polygon • Dreieck ist ein Polygon – Richtig • Dreieck enthält ein Polygon – Falsch ⇒ Dreieck wird von Polygon abgeleitet RT (ICS @ UIBK) Programmiermethodik 243/613 Vererbung und Polymorphismus Vererbung der Implementierung in Java Abstraktionsebenen • Vererbung einsetzen, wenn Superklasse und Subklasse konzeptionell auf unterschiedlichen Abstraktionsebenen stehen • Klassenname ist umgangssprachlich ein Oberbegriff des anderen Klassennamens • Beispiel RT (ICS @ UIBK) Programmiermethodik 244/613 Vererbung und Polymorphismus Abstrakte Klassen Übersicht Vererbung und Polymorphismus Vererbung Allgemein Vererbung der Spezifikation in Java Vererbung der Implementierung in Java Abstrakte Klassen Die Klasse Object RT (ICS @ UIBK) Programmiermethodik 245/613 Vererbung und Polymorphismus Abstrakte Klassen Abstrakte Klassen • Konkrete Superklassen und Interfaces bilden zwei Extreme • Abstrakte Klassen bilden Mittelweg • Enthalten Objektvariablen • Enthalten vollständige Methoden • Enthalten Schnittstellen (abstrakte Methoden) • Abstrakte Klasse wird mit dem Schlüsselwort abstract markiert • Zusätzlich werden abstrakte Methoden mit abstract gekennzeichnet • Abstrakte Klasse muss keine abstrakten Methoden enthalten • Wenn Klasse ein Interface nicht vollständig implementiert, dann muss sie abstrakte Klasse sein RT (ICS @ UIBK) Programmiermethodik 246/613 Vererbung und Polymorphismus Abstrakte Klassen Vererbung bei abstrakten Klassen • Von abstrakter Klasse können keine Objekte angelegt werden • Subklasse muss alle abstrakten Methoden implementieren, damit man von Subklasse Objekte anlegen kann • Implementiert Subklasse nur Teil (oder keine) der abstrakten Methoden, dann ist sie auch abstrakte Klasse • In Subklasse können neue Methoden definiert und Methoden überschrieben werden • Auch super kann verwendet werden • Beispiel: siehe Folie 247 RT (ICS @ UIBK) Programmiermethodik 247/613 Vererbung und Polymorphismus Abstrakte Klassen Beispiel p u b l i c a b s t r a c t c l a s s D e f a u l t S t a c k implements S t a c k { // p r o v i d e d e f a u l t i m p l e m e n t a t i o n f o r p e e k public Object peek ( ) { O b j e c t o = t h i s . pop ( ) ; t h i s . push ( o ) ; return o ; } // l e a v e r e m a i n i n g s t a c k o p e r a t i o n s open // f o r c o n c r e t e c l a s s e s p u b l i c a b s t r a c t O b j e c t pop ( ) ; p u b l i c a b s t r a c t boolean i s E m p t y ( ) ; p u b l i c a b s t r a c t v o i d push ( O b j e c t o b j ) ; } RT (ICS @ UIBK) Programmiermethodik 247/613 Vererbung und Polymorphismus Abstrakte Klassen Vergleich: Abstrakte Klasse - Interface • Unterschiede: Abstrakte Klassen bieten . . . • . . . abstrakte Methoden mit Zugriffsschutz protected und default (in Interface: alles public) • . . . Objektvariablen (nicht nur Konstanten) • . . . konkrete Methoden • . . . Konstruktoren, die von den Subklassen benutzt werden • Rein abstrakte Klassen sind möglich • Keine Objektvariablen • Nur abstrakte Methoden • Wozu dann Interfaces? • In Java: nur Einfachvererbung bei Klassen RT (ICS @ UIBK) Programmiermethodik 248/613 Vererbung und Polymorphismus Abstrakte Klassen Subtyping und Subclassing • Subtyping • Wenn eine Klasse ein Interface implementiert (von diesem Interface “erbt”) • Es wird nur der Typ “geerbt” • Subclassing • Wenn eine Klasse von einer andere Klasse erbt • Es wird die Implementierung geerbt RT (ICS @ UIBK) Programmiermethodik 249/613 Vererbung und Polymorphismus Abstrakte Klassen Varianten der Vererbung (Zusammenfassung) • Reine Vererbung der Spezifikation • Schnittstellen-Klassen (Interfaces in Java) • Vererbung der Spezifikation und Implementierung • Normalfall (auch in Java) • Unterklasse erbt Spezifikation und Implementierung • Reine Vererbung der Implementierung • Unterklasse übernimmt Implementierung, nicht Spezifikation • Für interne Nutzung (z.B. private Vererbung in C++) RT (ICS @ UIBK) Programmiermethodik 250/613 Vererbung und Polymorphismus Die Klasse Object Übersicht Vererbung und Polymorphismus Vererbung Allgemein Vererbung der Spezifikation in Java Vererbung der Implementierung in Java Abstrakte Klassen Die Klasse Object RT (ICS @ UIBK) Programmiermethodik 251/613 Vererbung und Polymorphismus Die Klasse Object Die Wurzelklasse Object • Jede Klasse, die von keiner Klasse erbt, erbt automatisch von der Wurzelklasse Object ⇒ Folgende Definitionen sind äquivalent • public class ClassName { ... } • public class ClassName extends Object { ... } • Damit werden alle Klassen direkt oder indirekt von Object abgeleitet RT (ICS @ UIBK) Programmiermethodik 252/613 Vererbung und Polymorphismus Die Klasse Object Vordefinierte Methoden • Object bietet einige Methoden an ⇒ Diese Methoden werden an jede Java-Klasse vererbt • Beispiele • public String toString () • • • • Liefert lesbare Repräsentation des Objekts (analog getInfo () im KFZ-Beispiel) public boolean equals(Object x) Prüft ob aktuelles Objekt und x gleich sind public int hashCode() Liefert Kennnummer (Hashcode) des Objekts protected Object clone() Liefert Kopie des Objekts protected void finalize () Wird vom Garbage Collector aufgerufen RT (ICS @ UIBK) Programmiermethodik 253/613 Vererbung und Polymorphismus Die Klasse Object Object: vollständige Methodenliste p u b l i c f i n a l n a t i v e C l a s s <?> g e t C l a s s ( ) ; p u b l i c n a t i v e i n t hashCode ( ) ; p u b l i c boolean e q u a l s ( O b j e c t o b j ) { . . . } protected native Object c l o n e ( ) throws C l o n e N o t S u p p o r t e d E x c e p t i o n ; public String toString () { . . . } public f i n a l native void n o t i f y ( ) ; public f i n a l native void n o t i f y A l l ( ) ; public f i n a l void wait ( ) throws I n t e r r u p t e d E x c e p t i o n { . . . } p u b l i c f i n a l n a t i v e v o i d w a i t ( long t i m e o u t ) throws I n t e r r u p t e d E x c e p t i o n ; p u b l i c f i n a l v o i d w a i t ( long t i m e o u t , i n t n a n o s ) throws I n t e r r u p t e d E x c e p t i o n { . . . } protected void f i n a l i z e ( ) throws Thr owab le { . . . } RT (ICS @ UIBK) Programmiermethodik 254/613 Vererbung und Polymorphismus Die Klasse Object Implementierungen in der Klasse Object • Minimale Implementierung • Methoden sollten in jeder Klasse entsprechend überschrieben werden • Wenn Methoden nicht überschrieben werden, wird minimale Implementierung aus Object verwendet • Beispiele • toString gibt Namen der Klasse zusammen mit Hashcode aus public String toString () { r e t u r n g e t C l a s s ( ) . getName ( ) + "@" + I n t e g e r . t o H e x S t r i n g ( hashCode ( ) ) ; } • equals vergleicht nur Referenzen p u b l i c boolean e q u a l s ( O b j e c t o b j ) { r e t u r n ( t h i s == o b j ) ; } RT (ICS @ UIBK) Programmiermethodik 255/613 Vererbung und Polymorphismus Die Klasse Object toString • Sinn: benutzerdefinierte Ausgabe eines Objekts • Spezielle Unterstützung in Kombination mit + • in someString + obj wird automatisch obj zu obj . toString () expandiert • Beispiel c l a s s Person { private String firstName ; private S t r i n g lastName ; ... public String toString () { return f i r s t N a m e + " " + lastName ; } } P e r s o n p = new P e r s o n ( " Hans " , " Mustermann " ) ; ... S t r i n g o u t p u t = "The current person is " + p ; RT (ICS @ UIBK) Programmiermethodik 256/613 Vererbung und Polymorphismus Die Klasse Object Typobjekte / getClass() • Typobjekte: genutzt für Java Reflection – siehe Entwurf von Softwaresystemen • Jedem Typ ist ein eindeutiges Typobjekt zugeordnet • Zugriff in Form: Type.class • Beispiel: System.out. println ( String . class) liefert "class java.lang.String" • Typobjekt eines Objekts obj kann mit obj . getClass () ermittelt werden • Beispiel: System.out. println ("Hello".getClass ()); liefert "class java.lang.String" RT (ICS @ UIBK) Programmiermethodik 257/613 Vererbung und Polymorphismus Die Klasse Object equals • Default-Implementierung vergleicht nur Referenzen • korrekte Implementierung erfüllt • Reflexivität • x. equals(x) • Symmetrie • x. equals(y) ⇒ y. equals(x) • Transitivität • x. equals(y) ⇒ y. equals(z) ⇒ x. equals(z) • Konsistenz • Objekte müssen bei wiederholten Aufrufen von equals immer gleiches Ergebnis liefern, solange sie sich nicht verändert haben • Alle Objekte sind von null verschieden • ! x. equals( null ) RT (ICS @ UIBK) Programmiermethodik 258/613 Vererbung und Polymorphismus Die Klasse Object Probleme mit equals • Überladen vs. Überschreiben (siehe Circle1.java, Circle2.java) • Probleme bei der Vererbung (siehe (Colored)Circle2.java, (Colored)Circle3.java) • Lösung 1: Verlange Typ-Gleichheit (siehe (Colored)Circle4.java) • Lösung 2: fixiere Vergleich in Oberklasse (siehe (Colored)Circle5.java) • Beachte instanceof in Kombination mit Lösung 2: trotz Gleichheit mittels equals kann Unterschied bei instanceof auftreten (siehe testInstanceof ) RT (ICS @ UIBK) Programmiermethodik 259/613 Vererbung und Polymorphismus Die Klasse Object hashCode • Für jedes Objekt sollte eindeutige Kennnummer produziert werden (nicht immer möglich) • Wird im Collection-Framework (später) benutzt • Anforderungen • Hashcode muss immer gleich bleiben, solange sich Objekt nicht ändert • Wenn Objekte gemäß equals gleich sind, muss hashCode gleiches Resultat liefern • Umkehrung gilt nicht, d.h. Objekte können gleichen Hashcode haben, aber verschieden sein RT (ICS @ UIBK) Programmiermethodik 260/613 Vererbung und Polymorphismus Die Klasse Object hashCode und equals • equals und hashCode hängen zusammen und sollten immer gemeinsam überschrieben werden • equals und hashCode sollten immer die gleichen Objektvariablen verwenden • man kann immer die hashCode-Methode von Referenzen verwenden (falls implementiert) • schlechte Beispiele: (Colored)Circle 2 / 3 • gute Beispiele: (Colored)Circle 4 / 5 RT (ICS @ UIBK) Programmiermethodik 261/613 Vererbung und Polymorphismus Die Klasse Object clone • Kopier-Konstruktor eignet sich zum Kopieren eines Objekts ohne Vererbung ( Circle c1 = new Circle(2.5); ...; Circle c2 = new Circle(c1); ) • Kopieren bei dynamischen Typ kann nur durch dynamisch gebundene Methode erfolgen: clone C i r c l e c1 = new C o l o r e d C i r c l e ( 2 . 5 , RED ) ; ...; C i r c l e c2 = new C i r c l e ( c1 ) ; // wrong C i r c l e c2 = c1 . c l o n e ( ) ; // ok • clone hat den Zugriffsschutz protected • Damit kann clone nicht von außen aufgerufen werden • Beim Überschreiben muss Zugriffsschutz auf public gelockert werden RT (ICS @ UIBK) Programmiermethodik 262/613 Vererbung und Polymorphismus Die Klasse Object Regeln für clone • Klasse muss • Interface Cloneable implementieren • eigene öffentliche Methode clone () implementieren • in clone Kopie des Superklassenobjekts mit super.clone() erzeugen • in clone alle Datenelemente veränderlicher Klassen einzeln mit clone-Aufrufen kopieren • clone kann nur verwendet werden, wenn jede verwendete Klasse clone korrekt implementiert • Beispiel: Address, Person, Teacher, CloneTest.java RT (ICS @ UIBK) Programmiermethodik 263/613 Ausnahmebehandlung Übersicht Ausnahmebehandlung Assertions Ausnahmen (Exceptions) RT (ICS @ UIBK) Programmiermethodik 264/613 Ausnahmebehandlung Motivation • Programme müssen Fehlersituationen erkennen und kontrolliert darauf reagieren • In Java • Assertions für Absicherung der inneren Programmlogik • Exceptions für Einhalten beliebiger Randbedingungen RT (ICS @ UIBK) Programmiermethodik 265/613 Ausnahmebehandlung Assertions Übersicht Ausnahmebehandlung Assertions Ausnahmen (Exceptions) RT (ICS @ UIBK) Programmiermethodik 266/613 Ausnahmebehandlung Assertions Assertions allgemein • Assertion (Zusicherung) ist Boolescher-Ausdruck, der immer zutreffen muss • Assertions werden beim Programmablauf von JVM überwacht • Programmabbruch, wenn Assertion nicht zutrifft • Assertions sind Ausdrücke • Form assert expr ; oder assert expr : string ; • expr muss immer true liefern, string enthält Fehlermeldung • Beispiele • assert a <= b && b <= c; • assert x >= 0: "negative x"; RT (ICS @ UIBK) Programmiermethodik 267/613 Ausnahmebehandlung Assertions Arbeitsweise • Assertions werden zur Laufzeit ausgewertet • Wenn Ergebnis false ist, stoppt Programm mit AssertionError • Nachfolgenden Anweisungen werden dann nicht mehr ausgeführt • Bei Abbruch wird Information über Ort der gescheiterten Assertion ausgegeben RT (ICS @ UIBK) Programmiermethodik 268/613 Ausnahmebehandlung Assertions Aktivierung • • • • • Assertions kosten Rechenzeit Können zur Laufzeit wahlweise aktiviert werden Deaktiviert sind sie automatisch! Programm muss nicht neu übersetzt werden Aktivierung im Programm Test: java −ea Test • Deaktivierung (default): java −da Test • Normalerweise aktiviert während Entwicklungszeit • Aktivierung kann zur Laufzeit festgestellt werden s t a t i c f i n a l boolean ASSERTIONS_ENABLED ; static { boolean a c t i v e = f a l s e ; assert ( a c t i v e = true ) ; ASSERTIONS_ENABLED = a c t i v e ; } RT (ICS @ UIBK) Programmiermethodik 269/613 Ausnahmebehandlung Assertions Einsatz von Assertions • Sind für Bedingungen geeignet, deren Einhaltung vom Programm selbst garantiert werden kann • Z.B. am Ende von Methode Rechenergebnisse prüfen • Nicht für Bedingungen geeignet, die von äußeren Einflüssen abhängen • Z.B. am Anfang von öffentlicher Methode Werte der Parameter überprüfen RT (ICS @ UIBK) Programmiermethodik 270/613 Ausnahmebehandlung Assertions Anwendung • Überprüfung von Parametern, die an nicht-öffentliche Methoden übergeben werden (nur falsch, wenn eigenes Programm fehlerhaft) • Verwendung in Postconditions, die am Ende einer Methode erfüllt sein müssen • Überprüfung von Schleifeninvarianten • Markierung von “toten Zweigen” in if - oder case-Anweisungen, die normalerweise niemals erreicht werden sollten (Assertion mit false als Argument) RT (ICS @ UIBK) Programmiermethodik 271/613 Ausnahmebehandlung Assertions public class AssertionTest { p r i v a t e s t a t i c i n t max ( f i n a l i n t x , f i n a l i n t y ) { return x < y ? x : y ; } p r i v a t e s t a t i c i n t min ( f i n a l i n t x , f i n a l i n t y ) { return x > y ? x : y ; } private s t a t i c void t e s t ( f i n a l i n t x , f i n a l i n t y ) { i n t maximum = A s s e r t i o n T e s t . max ( x , y ) ; i n t minimum = A s s e r t i o n T e s t . min ( x , y ) ; a s s e r t maximum >= minimum : "max < min" ; System . o u t . p r i n t l n ( maximum + " " + minimum ) ; } p u b l i c s t a t i c v o i d main ( f i n a l S t r i n g [ ] a r g s ) { AssertionTest . t e s t (10 , 15); AssertionTest . t e s t (8 , 3); AssertionTest . t e s t (2 , 2); } RT }(ICS @ UIBK) Programmiermethodik 272/613 Ausnahmebehandlung Assertions Private Invarianten-Methoden • Objektvariablen dürfen meist nicht beliebige Werte annehmen • Es gelten bestimmte Bedingungen • Bedingungen werden als Klasseninvarianten bezeichnet • Bedingungen gelten für jedes Objekt der Klasse • Bedingungen können während Ausführung einer Methode kurzfristig verletzt werden • Vor dem Aufruf und nach der Rückkehr müssen die Invarianten immer gelten • Klasseninvarianten können komplex sein • Mehrere Objektvariablen müssen berücksichtigt werden • Test kann aufwändig sein • Muss möglicherweise an vielen Stellen erfolgen • Private Invarianten-Methoden • Test der Klasseninvarianten wird in Boolean-Methode gegeben • Enthält keine Assertions • Wird in anderen Methoden bei Assertions verwendet RT (ICS @ UIBK) Programmiermethodik 273/613 Ausnahmebehandlung Assertions Beispiel public class Rational { p r i v a t e i n t denom ; ... p r i v a t e boolean i n v a r i a n t H o l d s r e t u r n denom != 0 ; } ... public void reduce ( ) { ... assert this . invariantHolds } ... public void m u l t i p l y ( R a t i o n a l ... assert this . invariantHolds } } RT (ICS @ UIBK) Programmiermethodik () { (); other ) { (); 274/613 Ausnahmebehandlung Ausnahmen (Exceptions) Übersicht Ausnahmebehandlung Assertions Ausnahmen (Exceptions) RT (ICS @ UIBK) Programmiermethodik 275/613 Ausnahmebehandlung Ausnahmen (Exceptions) Motivation • In laufendem Programm können Fehler auftreten • Logische Fehler im Programm • Fehlerhafte Bedienung • Probleme im Java-Laufzeitsystem • ... • Exceptions (Ausnahmen) sind ein Sprachmittel zur kontrollierten Reaktion auf Laufzeitfehler • Assertions sind Sonderfall davon RT (ICS @ UIBK) Programmiermethodik 276/613 Ausnahmebehandlung Ausnahmen (Exceptions) Exceptions • 2 Vorteile durch Exceptions • Fehler (und Exceptions) können nicht ignoriert werden ⇒ erfordert Maßnahmen zur Behandlung • Code für Programmablauf und Fehlerbehandlung wird getrennt • Exception-Handling • Ausnahmesituationen werden an bestimmten Punkten im Programm geprüft (und gemeldet) • An anderen Stellen steht Code zur Reaktion auf potenzielle Ausnahmesituationen RT (ICS @ UIBK) Programmiermethodik 277/613 Ausnahmebehandlung Ausnahmen (Exceptions) Grundprinzip der Ausnahmebehandlung • Information über Ausnahme wird in spezielles Objekt verpackt • Instanz der Klasse Exception (oder einer Subklasse davon) • Ausnahme kann auch explizit ausgelöst werden (mittels throw) • Ausnahme kann an bestimmter Stelle (äußerer Block, aufrufende Methode etc.) in einer catch-Klausel abgefangen werden • Grundkonstrukt: try-catch-Anweisung RT (ICS @ UIBK) Programmiermethodik 278/613 Ausnahmebehandlung Ausnahmen (Exceptions) Die try-catch Anweisung (Grundform) • Schema try { ... n o r m a l e r Code ... } catch ( E x c e p t i o n T y p e 1 e ) { . . . Fehlerbehandlung . . . } catch ( E x c e p t i o n T y p e 2 e ) { . . . Fehlerbehandlung . . . } catch . . . { ... } catch ( E x c e p t i o n T y p e x e ) { . . . Fehlerbehandlung . . . } RT (ICS @ UIBK) Programmiermethodik 279/613 Ausnahmebehandlung Ausnahmen (Exceptions) Ablauf try { stmtA ; • Normalfall (keine Fehler in stmtABC): stmtB ; Ausführung von stmtABCD stmtC ; } catch ( E1 e ) { • Ausnahme E1 in stmtB: Ausführung von stmtAB1D stmts1 ; } catch ( E2 e ) { • Ausnahme E2 in stmtB: stmst2 ; Ausführung von stmtAB2D } catch ( E3 e ) { • Ausnahme E4 in stmtB: stmst3 ; Ausführung von stmtAB, E4 muss an anderer } Stelle behandelt werden stmtD ; RT (ICS @ UIBK) Programmiermethodik 280/613 Ausnahmebehandlung Ausnahmen (Exceptions) Ablauf • Wird Ausnahme vom Typ E geworfen • Dann wird entsprechende catch-Klausel vom Typ E gesucht • Statt E kann auch Klausel mit Superklasse von E verwendet werden, da E dort substituiert werden kann • Reihenfolge der catch-Klauseln ist entscheidend • Ausnahme wird der Reihe nach mit catch-Klauseln verglichen • Ausgeführt wird catch-Klausel, zu der Ausnahme kompatibel ist • Nachfolgende catch-Klauseln werden ignoriert ⇒ Ordnung der catch-Klauseln sollte beachtet werden: von speziell zu allgemein • Wenn zuerst allgemeinere Ausnahme angegeben wird (und danach speziellere), dann kommt es zu Compile-Fehler RT (ICS @ UIBK) Programmiermethodik 281/613 Ausnahmebehandlung Ausnahmen (Exceptions) Ablauf • Falls keine catch-Klausel gefunden wird, wird in äußeren try-Blöcken gesucht • In verschachtelten try-Blöcken • Entlang der Methodenaufrufkette • Wird niemals catch-Klausel gefunden (auch nicht in main), dann bricht Programm ab RT (ICS @ UIBK) Programmiermethodik 282/613 Ausnahmebehandlung Ausnahmen (Exceptions) public class ExceptionTest { p u b l i c s t a t i c v o i d main ( f i n a l S t r i n g [ ] a r g s ) { try { int x , y ; x = Integer . parseInt ( args [ 0 ] ) ; y = Integer . parseInt ( args [ 1 ] ) ; System . o u t . p r i n t l n ( x / y ) ; } catch ( NumberFormatException e ) { System . o u t . p r i n t l n ( "no integer number " ) ; // a d d i t i o n a l e r r o r h a n d l i n g } catch ( A r r a y I n d e x O u t O f B o u n d s E x c e p t i o n e ) { System . o u t . p r i n t l n ( " provide 2 parameters " ) ; // a d d i t i o n a l e r r o r h a n d l i n g } catch ( A r i t h m e t i c E x c e p t i o n e ) { System . o u t . p r i n t l n ( " division by 0" ) ; // a d d i t i o n a l e r r o r h a n d l i n g } } RT }(ICS @ UIBK) Programmiermethodik 283/613 Ausnahmebehandlung Ausnahmen (Exceptions) Termination Model / Resumption Model • Termination Model • Kontrollfluss kehrt nicht mehr an Stelle zurück, an der Ausnahme aufgetreten ist • Die Ausnahmebehandlung in Java folgt dem Termination-Model • Resumption Model • Alternative zum Termination Model • Es erfolgt Rückkehr zur Aufrufstelle, d.h. nach Fehlerbehandlung wird Programm an der Stelle der Ausnahme fortgesetzt • Wird nicht in Java verwendet RT (ICS @ UIBK) Programmiermethodik 284/613 Ausnahmebehandlung Ausnahmen (Exceptions) Arten von Ausnahmen • Systemausnahmen • Werden automatisch ausgelöst (illegale Instruktionen) • Beispiele • ArithmeticException (bei Division durch 0) • NullPointerException (Zugriff auf null -Referenz) • ArrayIndexOutOfBoundsException (Arrayindex außerhalb des erlaubten Bereichs) • Können abgefangen werden, müssen es aber nicht • Benutzerausnahmen • Müssen explizit vom Programmierer ausgelöst werden (mittels throw-Anweisung) • Java-Bibliothek enthält schon häufige Fehlerarten (z.B. java . io .IOException) • Zusätzlich kann man eigene Ausnahme-Klassen implementieren und verwenden • Müssen abgefangen werden RT (ICS @ UIBK) Programmiermethodik 285/613 Ausnahmebehandlung Ausnahmen (Exceptions) Exception-Klassen • Ausnahmen sind in Java Objekte • Enthalten Informationen über aufgetretene Fehler • Bieten Methoden an, um auf Informationen zuzugreifen • Alle Ausnahmen sind in Klassenhierarchie gruppiert • Allgemeine Klasse Exception • Diverse Unterklassen für spezifische Ausnahmen • Dient zur Differenzierung • catch-Klausel, die Klasse E behandeln kann, kann auch alle Unterklassen von E behandeln RT (ICS @ UIBK) Programmiermethodik 286/613 Ausnahmebehandlung Ausnahmen (Exceptions) Hierarchie • Oberste Klasse ist Throwable • Enthält Methoden zur Fehleranalyse • String getMessage(): Text bei Ausnahme • String toString (): Klassenname + getMessage • void printStackTrace () • diverse Konstruktoren (leer, mit Fehlermeldung, . . . ) • Unterklassen • Error • irreparable Fehler • Exception • Fehler, die sinnvoll behandelt werden können • Existenz von Subklassen zur Fehlerbehandlung RT (ICS @ UIBK) Programmiermethodik 287/613 Ausnahmebehandlung Ausnahmen (Exceptions) Error • Error sind Fehler, die mit JVM in Verbindung stehen • Beispiel: Zu wenig Speicher für die JVM bei Objekterzeugung vorhanden ⇒ OutOfMemoryError • Da Fehler “abnormales” Verhalten anzeigen, müssen sie nicht mit catch-Klausel aufgefangen werden • Wie Systemausnahmen können sie abgefangen werden • Auffangen macht meist wenig Sinn: Wie sollte man auf Fehler reagieren? RT (ICS @ UIBK) Programmiermethodik 288/613 Ausnahmebehandlung Ausnahmen (Exceptions) Exception-Hierarchie • Exception • RuntimeException, Systemausnahmen (Unchecked Exceptions) • • • • • ArithmeticException NullpointerException IndexOutOfBoundsException MyRuntimeException ... ab hier: Benutzerausnahmen (Checked Exceptions) • java . io .IOException • java . io .FileNotFoundException • ... • InterruptedException • MyException • ... RT (ICS @ UIBK) Programmiermethodik 289/613 Ausnahmebehandlung Ausnahmen (Exceptions) Eigene Klasse / Ausnahme auslösen • Von Klasse Exception oder RuntimeException ableiten c l a s s MyExcept io n extends E x c e p t i o n {} (Hat nur einen Defaultkonstruktor) • Wenn man Nachricht mitgeben möchte c l a s s MyExcept io n extends E x c e p t i o n { p u b l i c MyE xc e pt io n ( ) {} p u b l i c MyE xc e pt io n ( S t r i n g i n f o ) { super ( i n f o ) ; } } • Auslösen (“Werfen”) einer Ausnahme mit throw-Anweisung throw new MyE xc e pt io n ( ) ; throw new MyE xc e pt io n ( " Falsche Eingabe " ) ; RT (ICS @ UIBK) Programmiermethodik 290/613 Ausnahmebehandlung Ausnahmen (Exceptions) Exception-Signatur • Methoden müssen Ausnahmen nicht lokal behandeln, sondern können sie weiterreichen • Benutzer einer Methode muss mit Exception-Signatur darauf hingewiesen werden • Form: type methodName(...) throws ExcepType1, ExcepType2, ... • Zeigt Aufrufer an, dass bestimmte Ausnahme geworfen werden könnte • Sollte möglichst spezifisch sein • Wird vom Compiler überprüft (Fehlende oder falsche Angaben führen zu Compile-Fehler) • Beispiel: Stack..., ArrayStack.java RT (ICS @ UIBK) Programmiermethodik 291/613 Ausnahmebehandlung Ausnahmen (Exceptions) Ausnahme durchreichen • Ausnahmen können durchgereicht werden • Methode generiert Ausnahme nicht selbst, sondern ruft Methode auf, die Ausnahme generiert • Methode muss in ihrer Signatur angeben • Typen der selbst ausgelösten Ausnahmen • Typen aller Ausnahmen aller aufgerufenen Methoden • RuntimeException und Subklassen müssen nicht angegeben werden • Compiler stellt sicher, dass keine Ausnahme von untergeordneter Methode übersehen wird • Beispiel: siehe Methode main in StackTest.java RT (ICS @ UIBK) Programmiermethodik 292/613 Ausnahmebehandlung Ausnahmen (Exceptions) Überladen und Überschreiben • Überladen • Exception-Signaturen überladener Methoden sind völlig unabhängig • Unterschiedliche Exception-Signaturen reichen nicht aus, um Methoden zu überladen • Überschreiben • Exception-Signatur darf bei der Redefinition der Methode nicht erweitert werden (neuer Exceptiontyp), nur verringert • Bei der Redefinition dürfen in der Exception-Signatur alle Typen aufscheinen, die zu Typ in der Signatur irgendeiner direkten oder indirekten Basisklassenmethode kompatibel sind RT (ICS @ UIBK) Programmiermethodik 293/613 Ausnahmebehandlung Ausnahmen (Exceptions) Beispiel class A { v o i d f o o ( i n t x ) throws I n t e r r u p t e d E x c e p t i o n { . . . } v o i d f o o ( S t r i n g s ) throws I O E x c e p t i o n { . . . } } c l a s s B extends A { void foo ( i n t x ) { . . . } v o i d f o o ( S t r i n g s ) throws F i l e N o t F o u n d E x c e p t i o n , EOFException { . . . } } c l a s s C extends B { // n o t okay v o i d b a r ( ) throws I n t e r r u p t e d E x c e p t i o n { . . . } v o i d b a r ( ) throws I O E x c e p t i o n { . . . } v o i d f o o ( S t r i n g x ) throws I O E x c e p t i o n { . . . } } RT (ICS @ UIBK) Programmiermethodik 294/613 Ausnahmebehandlung Ausnahmen (Exceptions) finally • try–catch-Block kann nach den catch-Klauseln eine finally -Klausel enthalten • Anweisungen in finally -Klausel werden immer als Abschluss der try-Anweisung ausgeführt, egal ob eine Ausnahme auftrat oder nicht • Zweck: Arbeiten sauber abschließen, die im try-Block begonnen wurden • Beispiel • Im try-Block wird Datei geöffnet • Datei muss wieder geschlossen werden (egal ob bei Verarbeitung der Daten Fehler auftritt oder nicht) • Auch bei verschachtelten try-Anweisungen möglich RT (ICS @ UIBK) Programmiermethodik 295/613 Ausnahmebehandlung Ausnahmen (Exceptions) Ablauf try { stmts0 ; } catch ( E1 e ) { • Normalfall (keine Fehler in stmts0): Ausführung von stmt034 stmts1 ; } catch ( E2 e ) { • Ausnahme E1 in stmts0: stmst2 ; Ausführung von stmts0134 } finally { • Ausnahme E3 in stmts0: stmst3 ; Ausführung von stmts013, E3 wird in } aufrufender Methode behandelt s t mt 4 ; • Beispiel: FinallyTest.java RT (ICS @ UIBK) Programmiermethodik 296/613 Ausnahmebehandlung Ausnahmen (Exceptions) Exception-Chaining • Wenn Methoden Ausnahmen immer weiterreichen • Sehr lange Exception-Signaturen • Detailfehler auf niederer Ebene müssen an ganz anderer Stelle behandelt werden • Änderungen in Exception-Signatur zieht viele Veränderungen nach sich • Lösung: Exception-Chaining • Mehrere Ausnahmen untergeordneter Aufrufe werden aufgefangen • Ausnahmen werden zusammengefasst und in neuer Ausnahme weitergegeben RT (ICS @ UIBK) Programmiermethodik 297/613 Ausnahmebehandlung Ausnahmen (Exceptions) Exception-Chaining Struktur try { ... } catch ( E1 ex ) { throw new MyExcept io n ( ex ) ; } catch ( E2 ex ) { throw new MyExcept io n ( ex ) ; } Ausnahmen vom Typ E1 und E2 werden in MyException verpackt RT (ICS @ UIBK) Programmiermethodik 298/613 Ausnahmebehandlung Ausnahmen (Exceptions) Chaining bei eigenen Ausnahmen • Entsprechende Konstruktoren implementieren • Exception-Klasse gibt Beispiele für solche Konstruktoren Exception( String message, Throwable cause) Exception(Throwable cause) • Beispiel für Konstruktor für die MyException-Klasse MyException(Throwable cause) { super(cause); } • Oder initCause -Methode verwenden catch ( E1 ex ) { M yException m = new M yE xc e pt io n ( ) ; m. i n i t C a u s e ( ex ) ; throw m; } • Beispiel: siehe ResourceLoader.java RT (ICS @ UIBK) Programmiermethodik 299/613 Ausnahmebehandlung Ausnahmen (Exceptions) Konstruktoren und Ausnahmen • Ausnahmen können auch in Konstruktoren verwendet werden • Fehler beim Anlegen eines Objekts sollten vermieden werden • Objekt könnte in inkonsistenten Zustand sein • Konstruktor sollte Ausnahme weiterreichen (throws) • Aufrufende Methode kann entsprechend auf gescheiterte Erzeugung des Objekts reagieren • Beispiel: public FileReader ( String filename ) throws FileNotFoundException RT (ICS @ UIBK) Programmiermethodik 300/613 Ausnahmebehandlung Ausnahmen (Exceptions) Debugging von Ausnahmen • Klasse Throwable liefert einige Methoden • printStackTrace liefert Aufrufstack der Methoden • getStackTrace - erlaubt Zugriff auf Stack-Trace-Elemente • getMessage - liefert Fehlerstring einer Ausnahme (wenn vorhanden) RT (ICS @ UIBK) Programmiermethodik 301/613 Ausnahmebehandlung Ausnahmen (Exceptions) Multi-Catch (ab Java 7) • Manchmal möchte man mehrere Ausnahmetypen gleichartig behandeln ⇒ nur eine catch-Klausel verwenden ⇒ Multi-Catch • Bei Aufzählung werden einzelnen Ausnahmen mit | getrennt • Beispiel try { ... } catch ( MyExc ep ti on | O t h e r E x c e p t i o n e ) { ... } RT (ICS @ UIBK) Programmiermethodik 302/613 Ausnahmebehandlung Ausnahmen (Exceptions) Multi-Catch • Abarbeitung erfolgt wie bei mehreren catch-Blöcken • Neben Standard-Tests kommen neue Überprüfungen hinzu, ob etwa gleiche Ausnahme mehrfach in Liste ist oder ob es Widersprüche durch Mengenbeziehungen gibt • Beispiel für fehlerhaftes Multi-Catch (Mengenbeziehung) try { . . . = new F i l e R e a d e r ( f i l e N a m e ) ; ... } catch ( F i l e N o t F o u n d E x c e p t i o n | I O E x c e p t i o n e ) { ... } RT (ICS @ UIBK) Programmiermethodik 303/613 Ausnahmebehandlung Ausnahmen (Exceptions) Final Rethrow (ab Java 7) • Wenn in catch-Block ein throw stattfindet, ermittelt Compiler die im try-Block tatsächlich aufgetretenen geprüften Ausnahmetypen • Im catch genannten Typ für das rethrow wird nicht berücksichtigt • Statt gefangenen Typ wird Compiler den durch die Codeanalyse gefundenen Typ beim rethrow melden RT (ICS @ UIBK) Programmiermethodik 304/613 Ausnahmebehandlung Ausnahmen (Exceptions) Beispiel: Final Rethrow c l a s s E x c e p t i o n A extends E x c e p t i o n {} c l a s s E x c e p t i o n B extends E x c e p t i o n {} public c l a s s Test { p r i v a t e v o i d methodA ( ) throws E x c e p t i o n A {} p r i v a t e v o i d methodB ( ) throws E x c e p t i o n B {} p r i v a t e s t a t i c v o i d methodC ( ) throws E x c e p t i o n A , E x c e p t i o n B { T e s t t = new T e s t ( ) ; try { t . methodA ( ) ; t . methodB ( ) ; } catch ( E x c e p t i o n e ) { throw e ; } } } RT (ICS @ UIBK) Programmiermethodik 305/613 Ausnahmebehandlung Ausnahmen (Exceptions) Verwendung von Ausnahmen – Allgemeine Regeln • Behandlung • Behandle auftretende Ausnahmen, wenn sinnvoll möglich • Propagiere im Zweifelsfall Ausnahmen an höhere Aufrufebenen weiter • Dabei sollte möglichst aussagekräftiger Ausnahmetyp gewählt werden • Art der Ausnahme • Wenn Aufrufer außergewöhnliche Situation behandeln kann, so sollte Benutzerausnahme geworfen werden • Ist Aufrufer nicht in der Lage, Fehlersituation zu korrigieren, so verwende Systemausnahme RT (ICS @ UIBK) Programmiermethodik 306/613 Ausnahmebehandlung Ausnahmen (Exceptions) Verwendung von Ausnahmen • Ausnahmen werden oft für Preconditions verwendet • Preconditions beziehen sich meist auf Parameter • Parameter dürfen meist nicht beliebige Werte annehmen • Ohne Überprüfung kann Objekt in falschem (inkonsistenten) Zustand sein • Verwendung von try-catch • try-catch findet sich meist in übergeordneten Methoden • Je mehr über aktuellen Programmzustand bekannt ist, desto besser lässt sich angemessen auf Fehler reagieren RT (ICS @ UIBK) Programmiermethodik 307/613 Ausnahmebehandlung Ausnahmen (Exceptions) Verwendung von Ausnahmen – Eigene Klassen definieren • Trade-Off • Viele Einzelklassen ⇒ Feingranulare Behandlung, aber lange Exception-Signaturen oder catch-Listen • Wenige Einzelklassen ⇒ Weniger Abfragen, aber schlechte Differenzierung • Hierarchien aufbauen (Subklassen von Exception oder RuntimeException) • Spezielle Klassen für differenzierte Fehlersituationen • Spezielle Klassen nach Fehlerart gruppieren und mit gemeinsamen Basisklassen versehen • Detaillierte Ausnahmen anbieten • Ausnahme beinhalten weitere Objektvariablen • Beim Werfen werden Objektvariablen belegt (z.B. mit den falschen Parameterwerten etc.) • Damit kann Programmierer auf mehr Information zugreifen RT (ICS @ UIBK) Programmiermethodik 308/613 Ausnahmebehandlung Ausnahmen (Exceptions) Verwendung der verschiedenen Basisklassen • Abfangen in catch-Klauseln • Error: nein • Exception: nein (würde alle Subklassen abfangen), nur Subklassen davon • RuntimeException: nein, eigentlich Fehler im Programm, der behoben werden sollte • Werfen • Error: ja, eventuell auch eigene Unterklasse • Exception: nein (zu allgemein), nur Unterklassen • RuntimeException: ja, aber gerne auch passende Unterklassen RT (ICS @ UIBK) Programmiermethodik 309/613 Ausnahmebehandlung Ausnahmen (Exceptions) Ausnahmen - Was man nicht machen soll • Niemals Ausnahme verschwinden lassen try { ... } catch ( MyExc ep ti on e ) {} • Fehler verschwinden nicht von selbst • Programm wird möglicherweise nicht richtig funktionieren (inkonsistente Daten etc.) • Ausnahmen sollten niemals Kontrollstrukturen ersetzen • Z.B. bei Arraydurchlauf nicht auf Länge überprüfen, sondern auf Ausnahme warten und dann abfangen • Rückgabe von null statt Ausnahme im Fehlerfall • Ausnahmen müssen behandelt werden, null kann ignoriert werden • Rückgabe von null ist nur in sehr wenigen Fällen sinnvoll • Muss in aufrufender Methode separat behandelt werden RT (ICS @ UIBK) Programmiermethodik 310/613 Pakete und Dokumentation Übersicht Pakete und Dokumentation Pakete Dokumentation: javadoc Dokumentation: UML RT (ICS @ UIBK) Programmiermethodik 311/613 Pakete und Dokumentation Pakete Übersicht Pakete und Dokumentation Pakete Dokumentation: javadoc Dokumentation: UML RT (ICS @ UIBK) Programmiermethodik 312/613 Pakete und Dokumentation Pakete Organisation von Klassen • Grundlegende Bausteine eines Java-Programms sind Klassen • Erzeugter Bytecode steht in Bytecodedateien • Einer pro Klasse (auch wenn mehrere Klassen in einer Datei stehen) • Konvention in Java • Eine Klasse pro Datei • Wenn mehrere Klassen in einer Datei vorhanden sind • Eine Klasse public • Alle anderen Klassen nicht public RT (ICS @ UIBK) Programmiermethodik 313/613 Pakete und Dokumentation Pakete Komplexität • Große Programme beinhalten viele Klassen • Probleme • Orientierung • Namenskonflikte • Verwaltung von Teilmengen • Lösung in Java • Pakete RT (ICS @ UIBK) Programmiermethodik 314/613 Pakete und Dokumentation Pakete Pakete • Paket • Sammlung mehrerer logisch zusammengehörender Klassen • Regeln • In einem Paket sollte eine Klasse eindeutig benannt werden • In unterschiedlichen Paketen kollidieren gleiche Namen nicht • Pakete werden benannt (wie Variablen etc.) • Pakete können geschachtelt werden • Höchstens ein Super-Package • Pakete bilden Baumstruktur • Namenskonventionen • http://www.oracle.com/technetwork/java/ codeconventions-135099.html • Beispiel: at.ac.uibk.cl-informatik.thiemann.myproject.mypackage RT (ICS @ UIBK) Programmiermethodik 315/613 Pakete und Dokumentation Pakete Beispiel project frontend text datastore web • Pakete • project • project.frontend • project.frontend.web • project.frontend.text • project.datastore RT (ICS @ UIBK) Programmiermethodik 316/613 Pakete und Dokumentation Pakete Abbildung auf Dateisystem • Pakethierarchie kann auf Verzeichnisse im Dateisystem abgebildet werden. • Beispiel (Unix) • • • • /home/dev CLASSPATH project.datastore Paket StorageHandler Klasse StorageHandler.class Bytecode für die Klasse ⇒ /home/dev/project/datastore/StorageHandler.class • CLASSPATH kann mehrere Startverzeichnisse enthalten • Erste gefundene Datei wird verwendet • Wenn nur eine Java-Datei vorhanden ist, wird class-Datei automatisch erzeugt RT (ICS @ UIBK) Programmiermethodik 317/613 Pakete und Dokumentation Pakete Organisationsschema • Pakete aus unterschiedlichen Quellen sollten verwendet werden können • Weltweit einheitliches Benennungsschema • Orientiert sich an Internet-Domainnamen • Domainnamen werden von hinten nach vorne auf Pakete und Subpakete abgebildet • Beispiel für Innsbruck • cl-informatik.uibk.ac.at ⇒ at.ac.uibk.cl-informatik • Ausnahmen • Standardklassen (z.B. String) - Paket java • Pakete unter javax RT (ICS @ UIBK) Programmiermethodik 318/613 Pakete und Dokumentation Pakete Qualifizierte Namen • Element eines Pakets kann explizit angesprochen werden • Beispiel: java . util . Arrays . sort (x ); • Ruft sort -Methode in Arrays-Klasse im java.util-Paket auf (util ist Subpaket) • Aufruf ähnlich wie Zugriff bei Objekten • Allgemeines Beispiel a.b.c • Klasse c im Paket a.b • Objektvariable c in Objektvariable b des Objekts a • Klassenvariable c der Klasse b im Paket a • Wird vom Compiler unterschieden (Kontext) RT (ICS @ UIBK) Programmiermethodik 319/613 Pakete und Dokumentation Pakete import-Klausel • Expliziter Aufruf ist umständlich • Elemente aus fremden Paketen können mit import zugänglich gemacht werden: import packagepath.classname; • packagepath ist beliebig langer Paketpfad • classname bestimmt Klasse • ∗ statt classname importiert alle Klassen eines Pakets • import-Klausel steht immer vor Klassendefinition • Mehrere import-Klauseln sind zulässig (Reihenfolge egal) • import-Klausel wird vom Compiler ausgewertet • Subpakete werden nicht automatisch eingebunden RT (ICS @ UIBK) Programmiermethodik 320/613 Pakete und Dokumentation Pakete package-Klausel • Legt Paketzugehörigkeit der entsprechenden Quelldatei fest • Syntax: package packagepath; • Nur eine Klausel ist zulässig (steht immer vor import-Klauseln) • Zusätzlich muss Quelldatei in Subdirectory entsprechend package-Klausel abgelegt werden RT (ICS @ UIBK) Programmiermethodik 321/613 Pakete und Dokumentation Pakete Default-Package • Wenn keine package-Klausel angegeben wird (wie bisher) • Klasse liegt im Default-Package • Wird auch als anonymes Paket bezeichnet • Default-Package ist einem Verzeichnis im CLASSPATH zugeordnet • Default-Package kann nicht importiert werden RT (ICS @ UIBK) Programmiermethodik 322/613 Pakete und Dokumentation Beispiel Pakete // A . j a v a package demo ; public class A { ... } // Demo . j a v a // d e f a u l t −p a c k a g e import demo . ∗ ; import demo . sub . C ; // B . j a v a package demo ; public class B { ... } p u b l i c c l a s s Demo { void t e s t ( ) { A a = new A ( ) ; B b = new B ( ) ; C c = new C ( ) ; } } // C . j a v a package demo . sub ; public class C { ... } RT (ICS @ UIBK) Verzeichnisstruktur: ../Demo.java ../demo/A.java ../demo/B.java ../demo/sub/C.java Programmiermethodik 323/613 Pakete und Dokumentation Pakete Namenskollisionen • Definition im eigenen Paket hat immer Vorrang • Importieren gleichnamiger Klassen aus anderen Paketen hat keine Auswirkung • Konkurrierende Definitionen in verschiedenen fremden Paketen müssen explizit unterschieden werden (trotz import-Klausel) RT (ICS @ UIBK) Programmiermethodik 324/613 Pakete und Dokumentation Pakete Statische import-Klausel • Stellt statisches Element (Objektvariablen, Methoden) einer Klasse so zur Verfügung, dass es ohne Qualifizierung (Klassennamen) benutzt werden kann • Beispiel: import s t a t i c j a v a . l a n g . Math . PI ; ... System . o u t . p r i n t l n ( PI + PI ) ; // ohne Math • Nur sinnvoll, wenn wiederholt gleiches statisches Element aus fremden Klasse gebraucht wird • Übermäßiger Gebrauch führt leicht zur Unübersichtlichkeit RT (ICS @ UIBK) Programmiermethodik 325/613 Pakete und Dokumentation Pakete Default-Zugriffsschutz • Wird kein Zugriffsschutz angegeben, dann wird Default-Zugriffsschutz (Package-Zugriffsschutz) verwendet • Alle Elemente mit Default-Zugriffsschutz können im gemeinsamen Paket verwendet werden • Alle Leistungen, die von Klassen in Paket untereinander angeboten werden, sollten diesen Zugriffsschutz erhalten • Sollte nur sparsam eingesetzt werden RT (ICS @ UIBK) Programmiermethodik 326/613 Pakete und Dokumentation Pakete Zugriffsschutz – Zusammenfassung private default protected public RT (ICS @ UIBK) Klasse 3 X 3 3 Paket 7 3 3 3 Subklasse(n) 7 7 3 3 Programmiermethodik Alle Klassen 7 7 7 3 327/613 Pakete und Dokumentation Pakete Archivdateien • Alternative Organisationsform für Pakete (jar-Dateien) • Vorteile • Leicht zusammenzuhalten • Kompression für effiziente Übertragung • Können digital signiert werden (oder andere Informationen enthalten) • Aber höherer Aufwand bei Zugriff • Können im CLASSPATH aufscheinen • Sind Einstiegspunkte bei Suche • Enthalten Pakethierarchie RT (ICS @ UIBK) Programmiermethodik 328/613 Pakete und Dokumentation Pakete jar-Tool • Kommandozeilenwerkzeug jar • Einige Schalter • Erzeugen (c = create, v = verbose, f = file) jar cvf jarfile bytecodefile bytecodefile ... • Inhalt auflisten (t = table of contents) jar tvf jarfile • Auspacken (x = extract) jar xvf jarfile • Applikationen können direkt aus Archiv gestartet werden • Jedes jar-Archiv enthält bestimmte Datei (Manifestdatei) mit Metainformationen • Man kann Eintrag mit Verweis auf main-Methode generieren • Dokumentation: http://docs.oracle.com/javase/tutorial/deployment/jar/ RT (ICS @ UIBK) Programmiermethodik 329/613 Pakete und Dokumentation Dokumentation: javadoc Übersicht Pakete und Dokumentation Pakete Dokumentation: javadoc Dokumentation: UML RT (ICS @ UIBK) Programmiermethodik 330/613 Pakete und Dokumentation Dokumentation: javadoc Motivation • Konsistente Dokumentation von Quelltexten ist mühsam • Häufig: Quelltext und Dokumentation in verschiedenen Dateien • Aktueller Stand des Quelltextes kann sich von Dokumentation unterscheiden (Programm funktioniert auch ohne neue Dokumentation) • Java hebt diese Trennung auf • Eine einzige Datei • Spezielle Kommentare (Doc-Kommentare) /∗ ∗ ... ∗/ RT (ICS @ UIBK) Programmiermethodik 331/613 Pakete und Dokumentation Dokumentation: javadoc Aufbau von Doc-Kommentaren • Werden nicht beliebig im Text verstreut • Stehen vor Definition von • Klassen und Interfaces • Methoden • Datenelementen • Aufbau (typisch) • Zusammenfassung in einem Satz mit Punkt am Ende • Ausführliche Beschreibung • Liste von Tags, die bestimmte zusätzliche Ausgaben erzeugen • Weitere Informationen: http://www.oracle.com/technetwork/ java/javase/documentation/index-137868.html RT (ICS @ UIBK) Programmiermethodik 332/613 Pakete und Dokumentation Dokumentation: javadoc Tags • Tags markieren Informationen mit bestimmter Bedeutung • Bestehen aus @ und Schlüsselwort • Nach Tag folgt Beschreibung • Stehen am Anfang von neuen Zeile RT (ICS @ UIBK) Programmiermethodik 333/613 Pakete und Dokumentation Dokumentation: javadoc Tags (Beispiele) • Für Klassen / Interfaces • @author text • @version text • @since version • @see reference (Klasse, auch bei Methoden) • Methoden • @param name text • @return text • @throws exceptionclass text • @deprecated text (markiert veraltete Methode, die nicht mehr verwendet werden soll) • Datenelemente • Keine Tags • Weitere Tags siehe http://www.oracle.com/technetwork/java/ javase/documentation/index-jsp-135444.html RT (ICS @ UIBK) Programmiermethodik 334/613 Pakete und Dokumentation Dokumentation: javadoc javadoc-Compiler • Für Dokumentation gibt es eigenen Compiler: javadoc • Übersetzt Dokumentation in HTML-Format • javac ignoriert Dokumentation • Einige Schalter -d path -public -private -author -version -help Speicher-Verzeichnis Nur public-Elemente werden in Doku aufgenommen Alle Elemente werden in Dokumentation aufgenommen Übernimmt das @author-Tag (nicht default) Übernimmt das @version-Tag (nicht default) Hilfe zu javadoc • Aufruf (Beispiel) • javadoc –private BankAccount.java • Project / Generate Javadoc • Tools / Project Documentation RT (ICS @ UIBK) Programmiermethodik (Kommandozeile) (Eclipse) (BlueJ) 335/613 Pakete und Dokumentation Dokumentation: javadoc Kommentare in HTML • Inhalt von Doc-Kommentaren wird in HTML-Dateien übersetzt ⇒ HTML-Tags verwendbar • Sollten sinnvoll und korrekt sein • Beispiel @author Rene Thiemann <a href=mailto:[email protected]> rene [email protected]</a> • Erzeugte Dateien • Mehrere HTML-Dateien • Startpunkt: index.html RT (ICS @ UIBK) Programmiermethodik 336/613 Pakete und Dokumentation Dokumentation: UML Übersicht Pakete und Dokumentation Pakete Dokumentation: javadoc Dokumentation: UML RT (ICS @ UIBK) Programmiermethodik 337/613 Pakete und Dokumentation Dokumentation: UML Modell und Diagramm • Modell stellt Abstraktion eines Realitätsausschnitts dar • Um Informationen verständlicher darzustellen (Analog: Baupläne von Gebäuden) • Um essentielle Systemaspekte aufzuzeigen • Zur Kommunikation (mit Projektmitarbeitern oder Kunden) • Um komplexe Architekturen darstellen zu können • Diagramm ist die grafische Repräsentation eines Modells RT (ICS @ UIBK) Programmiermethodik 338/613 Pakete und Dokumentation Dokumentation: UML Unified Modeling Language (UML) • Unified Modeling Language (UML) ist standardisierte ausdruckstarke Modellierungssprache • Mit Hilfe von UML können Softwaresysteme entworfen, analysiert und dokumentiert werden • Begriff Unified bedeutet • Unterstützung des gesamten Entwicklungsprozesses • Unabhängigkeit von Entwicklungswerkzeugen, sowie Programmiersprachen oder auch Anwendungsbereichen • UML ist aber nicht • Allheilmittel und vollständig • vollständiger Ersatz für eine Textbeschreibung • Methode oder Vorgehensmodell RT (ICS @ UIBK) Programmiermethodik 339/613 Pakete und Dokumentation Dokumentation: UML Diagrammarten • Etliche unterschiedliche Diagrammarten • Klassendiagramm (dieser Abschnitt) • Beschreibt den strukturellen Aspekt (Klassen, Interfaces, Beziehungen) • Sequenzdiagramm (Abschnitt über Entwurfsmuster) • Beschreibt komplexe Interaktionen zwischen Objekten in bestimmten Rollen • Beschreibt zeitliche Abfolge der Interaktionen • ... RT (ICS @ UIBK) Programmiermethodik 340/613 Pakete und Dokumentation Dokumentation: UML Notation für Klassen Sprachkonzept Notation className Klasse className Klasse mit Abschnitten attribute1 attribute2 method1 method2 RT (ICS @ UIBK) Programmiermethodik 341/613 Pakete und Dokumentation Dokumentation: UML Klassen (Attribute) • Sichtbarkeit für Attribute und Operationen • + = public • # = protected • − = private • ~ = default • Instanzattribute oder Klassenattribute • Klassenattribute werden unterstrichen • Zusätzliche Eigenschaften angeben • «readOnly» • «ordered» • «unique» • «nonunique» • ... RT (ICS @ UIBK) Programmiermethodik 342/613 Pakete und Dokumentation Dokumentation: UML Klassen (Multiplizität) • Multiplizität von Attributen • Spezifiziert wie viele Werte ein Attribut aufnehmen kann • Form: attribute: type[a..b] • a..b • mindestens a, höchstens b • a und b sind natürliche Zahlen • * statt b bedeutet beliebig viele • Beispiele • 1..1 genau ein (entspricht 1) • 0..1 keins oder eins • 0..* beliebig viele (entspricht *) • 1..* mindestens eins RT (ICS @ UIBK) Programmiermethodik 343/613 Pakete und Dokumentation Dokumentation: UML Klassen (Operationen) • Angabe einer (eventuell leeren) Parameterliste für jede Operation • Für jeden Parameter muss zumindest Name und Typ angegeben werden (auch Multiplizität) • Auch Rückgabetyp möglich (wenn nichts angegeben: void) • Unterstreichen kennzeichnet Klassenoperationen • Sichtbarkeit wie bei Attributen • Zusätzliche Eigenschaften • «abstract» (oder kursiv geschrieben) • «query» (Methode ohne Seiteneffekte) • «leaf» (wenn final ) • «raisedException» (wie throws) • Hinweise auf Algorithmen können in Notiz angefügt werden RT (ICS @ UIBK) Programmiermethodik 344/613 Pakete und Dokumentation Dokumentation: UML Beispiele Alle Attribute sind privat Stack –maxSize : int –position : int –data : int[0..*] «constructor»+Stack(maxSize : int) +push(element : int) +pop() : int +isEmpty() : boolean +size() : int User –name : String[1] –key : Password[1..*] Bereich kann leer bleiben (hier: Operationen) Alle Operation sind öffentlich RT (ICS @ UIBK) User kann mehrere Passwörter haben Programmiermethodik 345/613 Pakete und Dokumentation Dokumentation: UML Assoziation A B • Grundform (binäre Assoziation) • Zusätzliche Angaben • Benennung (in der Mitte) • Rollen (an den Enden der Assoziation, spezifische Funktion angeben) • Multiplizitäten (an den Enden, wie bei Attributen) • Angabe von Eigenschaften • «ordered» • «unique» • ... • Navigationsangaben • Zulässige Navigationsrichtung (durch Pfeil) • Keine Navigation erlaubt (durch X) RT (ICS @ UIBK) Programmiermethodik 346/613 Pakete und Dokumentation Dokumentation: UML Beispiele User Password has User has –key Password * Reflexive Assoziation User –owner 1 has –key Password * SortedList «constructor»+SortedList() +insert(element : int) +print() RT (ICS @ UIBK) Node –head 0..1 –data : int «constructor»˜Node(data : int) Programmiermethodik 0..1 –next 347/613 Pakete und Dokumentation Dokumentation: UML Beispiel (Java Umsetzung – Grundformen) User –key Password User * –owner 1 –key Password * public c l a s s User { private Passwort [ ] key ; ... } public c l a s s User { private Passwort [ ] key ; ... } p u b l i c c l a s s Password { ... ... } p u b l i c c l a s s Password { p r i v a t e U s e r owner ; ... } RT (ICS @ UIBK) Programmiermethodik 348/613 Pakete und Dokumentation Dokumentation: UML Beispiel (Java Umsetzung) Borrower –currentBorrower 0..1 borrows public c l a s s Borrower { p r i v a t e Book [ ] b o r r o w e d B o o k s ; p r i v a t e i n t numBooks –borrowedBooks 0..5 Book p u b l i c c l a s s Book { private Borrower currentBorrower ; public Borrower ( ) { public void setBorrower ( numBooks = 0 ; Borrower b ) { b o r r o w e d B o o k s = new Book [ 5 ] ; currentBorrower = b ; } } ... p u b l i c v o i d b o r r o w ( Book b ) { } ... b o r r o w e d B o o k s [ numBooks ] = b ; numBooks++; b . setBorrower ( this ) ; ... } ... } RT (ICS @ UIBK) Programmiermethodik 349/613 Pakete und Dokumentation Dokumentation: UML Aggregation • Ist spezielle Assoziation (Teil-Ganzes-Beziehung) • Komposition ist speziellere (strengere) Form der Aggregation mit folgenden Einschränkungen • Ein Teil darf Kompositionsteil höchstens eines Ganzen sein • Multiplizität 1 bedeutet, dass Teil nur solange existiert wie sein Ganzes • Beispiele Company Division has 1 Invoice 1..* Invoice Line Item has 1 1..* Aggregation Komposition Rechnungsposten existiert nur mit Rechnung RT (ICS @ UIBK) Programmiermethodik 350/613 Pakete und Dokumentation Dokumentation: UML Beispiel (Java Umsetzung) Car has –wheels Wheel 4 Car has –wheels Wheel 4 p u b l i c c l a s s Car { p u b l i c c l a s s Car { p r i v a t e Wheel [ ] w h e e l s ; p r i v a t e Wheel [ ] w h e e l s ; ... ... p u b l i c Car ( Wheel w1 , . . . ) { p u b l i c Car ( ) { w h e e l s = new Wheel [ 4 ] ; w h e e l s = new Wheel [ 4 ] ; w h e e l s [ 0 ] = w1 ; w h e e l s [ 0 ] = new Wheel ( ) ; w h e e l s [ 1 ] = w2 ; w h e e l s [ 1 ] = new Wheel ( ) ; w h e e l s [ 2 ] = w3 ; w h e e l s [ 2 ] = new Wheel ( ) ; w h e e l s [ 3 ] = w4 ; w h e e l s [ 3 ] = new Wheel ( ) ; ... ... } } } } RT (ICS @ UIBK) Programmiermethodik 351/613 Pakete und Dokumentation Dokumentation: UML Vererbung und Interfaces ArrayStack «interface» Stack +push(data : Object) +pop() : Object +isEmpty() : boolean # stack : Object[] # position : int +push(data : Object) +pop() : Object +isEmpty() : boolean +isFull() : boolean Implemetierung Vererbung ResizableArrayStack +resize(preferredSize : int) RT (ICS @ UIBK) Programmiermethodik 352/613 Generische Programmierung Übersicht Generische Programmierung Motivation Generizität Type-Erasure Polymorphe Methoden RT (ICS @ UIBK) Programmiermethodik 353/613 Generische Programmierung Motivation Übersicht Generische Programmierung Motivation Generizität Type-Erasure Polymorphe Methoden RT (ICS @ UIBK) Programmiermethodik 354/613 Generische Programmierung Motivation Implementierung von Paaren verschiedener Typen public class IPair { private f i n a l Integer f i r s t ; p r i v a t e f i n a l I n t e g e r second ; public IPair ( Integer first , Integer this . first = first ; t h i s . second = second ; } public Integer getFirst () { return this . f i r s t ; } p u b l i c I n t e g e r getSecond () { r e t u r n t h i s . second ; } } second ) { p u b l i c c l a s s DPair { p r i v a t e f i n a l Double f i r s t ; p r i v a t e f i n a l Double second ; p u b l i c DPair ( Double f i r s t , Double second ) { this . first = first ; t h i s . second = second ; } p u b l i c Double g e t F i r s t ( ) { return this . f i r s t ; } p u b l i c Double getSecond ( ) { r e t u r n t h i s . second ; } } RT (ICS @ UIBK) Programmiermethodik 355/613 Generische Programmierung Motivation Object-Paare public class Pair { private f i n a l Object f i r s t ; private f i n a l Object second ; public Pair ( Object f i r s t , Object second ) { this . f i r s t = f i r s t ; t h i s . second = second ; } public Object g e t F i r s t () { return t h i s . f i r s t ; } public Object getSecond () { return t h i s . second ; } } • Wurzelklasse Object und Ersetzungsprinzip ausnutzen ⇒ Problem gelöst? ⇒ Typsicherheit? RT (ICS @ UIBK) Programmiermethodik 356/613 Generische Programmierung Motivation Allgemeine Implementierung • Es werden nur Objekte vom Typ Object verwaltet ⇒ Alle Objekte (durch Autoboxing auch primitive Datentypen) können verwaltet werden ⇒ Eine Implementierung für unterschiedliche Typen • Aber • Getter-Methoden liefern nur Objekt vom Typ Object ⇒ weitere Benutzung erfordert Casting Pair p = new Pair("foo","bar"); String s = (String) p. getFirst (); • Es können gleichzeitig unterschiedliche Typen (z.B. Integer , String etc.) gespeichert werden (Typ ist nicht vorhersagbar) Pair stringPair = new Pair(2,"foo"); ⇒ Keine Typsicherheit und daher umständliche Programmierung notwendig • Lösung? RT (ICS @ UIBK) Programmiermethodik 357/613 Generische Programmierung Generizität Übersicht Generische Programmierung Motivation Generizität Type-Erasure Polymorphe Methoden RT (ICS @ UIBK) Programmiermethodik 358/613 Generische Programmierung Generizität Generizität • Generizität erlaubt es, Programmteil (Klasse, Interface, Methode) mit Typen zu parametrisieren • Seit Java 1.5 • Unterscheidung • Generische Klasse • Generischer Typ RT (ICS @ UIBK) Programmiermethodik 359/613 Generische Programmierung Generizität Generische Klasse • Definition • Wie normale Klasse • Zusätzlich wird der Klasse eine Typvariable in spitzen Klammern nachgestellt: public class Pair<T> {...} • Kann beliebiger Buchstabe sein • <T> ist aber Konvention • Im Klassenrumpf wird Typvariable fast wie normaler Typ verwendet • Bei Übergabe- bzw. Rückgabeparameter etc. • Einschränkungen werden noch erklärt RT (ICS @ UIBK) Programmiermethodik 360/613 Generische Programmierung Generizität Generischer Typ • Bei Anwendung wird für generische Typvariable ein konkretes Typargument übergeben • Generische Klasse und Typargument liefern generischen Typ • Kann wie jeder andere Typ verwendet werden • Variablendeklaration • Methodenparameter • Rückgabeparameter • ... • Beispiel (Pair): Pair<Integer> p = new Pair<Integer>(10,10); RT (ICS @ UIBK) Programmiermethodik 361/613 Generische Programmierung Generizität Beispiel: Pair p u b l i c c l a s s P a i r <T> { private f i n a l T f i r s t ; private f i n a l T second ; public Pair ( f i n a l T f i r s t , f i n a l T second ) { this . f i r s t = f i r s t ; t h i s . second = second ; } public T g e t F i r s t () { return th is . f i r s t ; } public T getSecond () { return t h i s . second ; } } RT (ICS @ UIBK) Programmiermethodik 362/613 Generische Programmierung Generizität Beispiel: Anwendung public c l a s s Test { p r i v a t e s t a t i c v o i d p r i n t I n t P a i r ( P a i r <I n t e g e r > i ) { System . o u t . p r i n t l n ( i . g e t F i r s t ( ) + " " + i . getSecond ( ) ) ; } p u b l i c s t a t i c v o i d main ( f i n a l S t r i n g [ ] a r g s ) { P a i r <I n t e g e r > p i = new P a i r <I n t e g e r >(10 , 1 0 ) ; P a i r <S t r i n g > p s = new P a i r <S t r i n g >(" EINS " , "2" ) ; // P a i r <S t r i n g > p s i = new P a i r <S t r i n g >("EINS " , 2 ) ; printIntPair ( pi ); // p r i n t I n t P a i r ( p s ) ; } } RT (ICS @ UIBK) Programmiermethodik 363/613 Generische Programmierung Generizität Generische Typen • Pair<Integer> und Pair<String> sind unterschiedliche (inkompatible) Typen • Können nicht zugewiesen werden • Keine Substitution möglich (wenn z.B. Pair<Integer> formaler Parameter ist, und Pair<String> Typ des aktuellen Parameters ist) • Alle Methoden mit Rückgabewerten liefern jetzt Ergebnis des Typarguments (kein Cast notwendig) • Beim Übersetzen überprüft Compiler korrekte Zuweisungen, Verwendungen, etc. • Statische Typprüfung durch Compiler verhindert Übersetzung von Programmen mit Typfehlern • Zur Laufzeit finden keine Tests statt RT (ICS @ UIBK) Programmiermethodik 364/613 Generische Programmierung Generizität Generische Interfaces • Auch Interfaces können generisch definiert werden • Beispiel p u b l i c i n t e r f a c e Stack <T> { v o i d push (T d a t a ) ; T pop ( ) ; boolean i s E m p t y ( ) ; } • Implementierung • Durch Klasse, wobei Interface mit konkreten Typargument versehen wird • Durch generische Klasse, wobei Typvariablen der Klasse und des Interfaces gekoppelt werden RT (ICS @ UIBK) Programmiermethodik 365/613 Generische Programmierung Generizität Beispiel mit konkretem Typargument p u b l i c c l a s s S t r i n g S t a c k implements Stack <S t r i n g > { p r i v a t e S t r i n g [ ] d a t a = new S t r i n g [ 2 0 ] ; int position = 0; p u b l i c v o i d push ( S t r i n g d a t a ) { t h i s . data [ t h i s . p o s i t i o n ] = data ; t h i s . p o s i t i o n ++; } p u b l i c S t r i n g pop ( ) { t h i s . p o s i t i o n −−; return t h i s . data [ t h i s . p o s i t i o n ] ; } p u b l i c boolean i s E m p t y ( ) { r e t u r n t h i s . p o s i t i o n == 0 ; } RT (ICS @ UIBK) Programmiermethodik 366/613 Generische Programmierung Generizität Beispiel mit konkretem Typargument: Anwendung public s t a t i c void t e s t ( ) { S t r i n g S t a c k s t a c k = new S t r i n g S t a c k ( ) ; s t a c k . push ( "foo" ) ; Stack <S t r i n g > s s t a c k = s t a c k ; S t r i n g s = s s t a c k . pop ( ) ; // s s t a c k . push ( 5 ) ; // s t a c k . push ( 5 ) ; } RT (ICS @ UIBK) Programmiermethodik 367/613 Generische Programmierung Generizität Beispiel mit generischem Typargument p u b l i c c l a s s L i s t S t a c k <T> implements Stack <T> { p r i v a t e Node<T> r o o t = n u l l ; p u b l i c boolean i s E m p t y ( ) { r e t u r n t h i s . r o o t == n u l l ; } p u b l i c v o i d push (T d a t a ) { t h i s . r o o t = new Node<T>( data , t h i s . r o o t ) ; } p u b l i c T pop ( ) { T data = t h i s . root . data ; this . root = this . root . next ; return data ; } } c l a s s Node<T> { T data ; Node<T> n e x t ; Node (T data , Node<T> n e x t ) { t h i s . data = data ; this . next = next ; } } RT (ICS @ UIBK) Programmiermethodik 368/613 Generische Programmierung Generizität Beispiel mit generischem Typargument: Anwendung public s t a t i c void t e s t ( ) { L i s t S t a c k <S t r i n g > s t a c k = new L i s t S t a c k <S t r i n g > ( ) ; s t a c k . push ( "foo" ) ; Stack <S t r i n g > s s t a c k = s t a c k ; S t r i n g s = s s t a c k . pop ( ) ; // s s t a c k . push ( 5 ) ; // s t a c k . push ( 5 ) ; Stack <I n t e g e r > i s t a c k = new L i s t S t a c k <I n t e g e r > ( ) ; i s t a c k . push ( 5 ) ; i n t i = i s t a c k . pop ( ) ; // i s t a c k . push ( " f o o " ) ; Stack <O b j e c t > i s t a c k 2 = new L i s t S t a c k <O b j e c t > ( ) ; i s t a c k 2 . push ( 1 ) ; // i = i s t a c k 2 . pop ( ) ; i s t a c k 2 . push ( "foo" ) ; } RT (ICS @ UIBK) Programmiermethodik 369/613 Generische Programmierung Generizität Mehrere Typvariablen • Generische Klasse kann auch mehrere Typvariablen haben • Typvariablen sind unabhängig voneinander • Typargumente können frei gewählt werden • Statische Typprüfung stellt sicher, dass konsistente Zuweisungen erfolgen • Generische Typen sind selbst vollwertige Typen, d.h. sie können auch als Typargumente verwendet werden RT (ICS @ UIBK) Programmiermethodik 370/613 Generische Programmierung Generizität Beispiel: Pair p u b l i c c l a s s P a i r <S , T> { private f i n a l S f i r s t ; private f i n a l T second ; public Pair ( f i n a l S f i r s t , f i n a l T second ) { this . f i r s t = f i r s t ; t h i s . second = second ; } public S g e t F i r s t () { return th is . f i r s t ; } public T getSecond () { return t h i s . second ; } } RT (ICS @ UIBK) Programmiermethodik 371/613 Generische Programmierung Generizität Beispiel: Pair-Anwendung public s t a t i c void t e s t ( ) { P a i r <S t r i n g , I n t e g e r > p s i ; p s i = new P a i r <S t r i n g , I n t e g e r >("TEST" , 1 7 ) ; String s = psi . getFirst (); i n t i = p s i . getSecond ( ) ; // p s i = new P a i r <S t r i n g , S t r i n g >("TEST " , " 1 " ) ; P a i r <I n t e g e r , P a i r <S t r i n g , I n t e g e r >> pp = new P a i r <I n t e g e r , P a i r <S t r i n g , I n t e g e r >>(2, p s i ) ; I n t e g e r j = pp . g e t S e c o n d ( ) . g e t S e c o n d ( ) ; L i s t <L i s t <Double>> m a t r i x ; L i s t <P a i r <S t r i n g , O b j e c t >> map ; } RT (ICS @ UIBK) Programmiermethodik 372/613 Generische Programmierung Generizität Typebounds • Normalerweise werden beliebige Typen als Typargumente akzeptiert • Oft möchte man aber spezielle generische Klasse mit bestimmten Methoden einer Klasse implementieren • Typargumente können daher eingeschränkt werden • Nach dem Typ wird ein Typebound genannt • Typebound kann beliebiger Typ sein (kann auch Typvariablen einbeziehen) • Typargumente müssen zum Typebound kompatibel sein RT (ICS @ UIBK) Programmiermethodik 373/613 Generische Programmierung Generizität public class A { } p u b l i c c l a s s B extends A { public void b ( ) { } } p u b l i c c l a s s C extends B { } p u b l i c c l a s s P a i r <T extends B> { private f i n a l T f i r s t ; private f i n a l T second ; p u b l i c P a i r (T f i r s t , T s e c o n d ) { this . f i r s t = f i r s t ; t h i s . second = second ; } public T g e t F i r s t () { t h i s . f i r s t . b ( ) ; // p o s s i b l e s i n c e T e x t e n d s B return t h i s . f i r s t ; } } RT (ICS @ UIBK) Programmiermethodik 374/613 Generische Programmierung Generizität Beispiel Anwendung public s t a t i c void t e s t ( ) { P a i r <B> pb = new P a i r <B>(new B ( ) , new B ( ) ) ; P a i r <C> pc = new P a i r <C>(new C ( ) , new C ( ) ) ; // P a i r <A> pa = new P a i r <A>(new A ( ) , new A ( ) ) ; } RT (ICS @ UIBK) Programmiermethodik 375/613 Generische Programmierung Generizität Typebounds • Schlüsselwort extends wird bei Typebounds für Klassen und Interfaces verwendet • Typvariable kann mit mehreren Typvariablen eingeschränkt werden (mit & verknüpfen) public class Pair<T extends A & B & C & ...> { ... } • Erster Typ (A) kann beliebiger Typ sein • Spätere Typen (B, C, . . . ) dürfen nur Interfaces sein RT (ICS @ UIBK) Programmiermethodik 376/613 Generische Programmierung Generizität Typebounds mit Typvariablen • Typvariable kann auch bei Formulierung von Typebounds verwendet werden • Beispiel mit Interface Comparable<T>: p u b l i c i n t e r f a c e Comparable<T> { i n t compareTo (T o t h e r ) ; // n e g a t i v e (<) , 0 (=) , p o s i t i v e (>) } • Alle Elemente in SortedList sollten vergleichbar sein, d.h. das Interface Comparable<T> implementieren public class SortedList <T extends Comparable<T>> {...} • Zulässige Deklaration: SortedList <Integer> = ...; • Unzulässige Deklaration: SortedList <Object> = ...; (Object implementiert nicht Comparable<Object>) RT (ICS @ UIBK) Programmiermethodik 377/613 Generische Programmierung Generizität p u b l i c c l a s s S o r t e d L i s t <T extends Comparable<T>> { p r i v a t e Node<T> r o o t = n u l l ; p r i v a t e Node<T> i n s e r t (T data , Node<T> node ) { i f ( node == n u l l | | d a t a . compareTo ( node . d a t a ) < 0 ) { r e t u r n new Node<T>( data , node ) ; } else { node . n e x t = i n s e r t ( data , node . n e x t ) ; r e t u r n node ; } } p u b l i c v o i d i n s e r t (T d a t a ) { t h i s . r o o t = i n s e r t ( data , t h i s . r o o t ) ; } public void p r i n t ( ) { f o r ( Node<T> c u r r e n t = t h i s . r o o t ; c u r r e n t != n u l l ; current = current . next ) System . o u t . p r i n t l n ( c u r r e n t . d a t a ) ; } } RT (ICS @ UIBK) Programmiermethodik 378/613 Generische Programmierung Generizität Anwendung public s t a t i c void t e s t ( ) { S o r t e d L i s t <S t r i n g > l i s t = new S o r t e d L i s t <S t r i n g > ( ) ; l i s t . i n s e r t ( "foo" ) ; l i s t . i n s e r t ( "bar" ) ; l i s t . i n s e r t ( "com" ) ; l i s t . p r i n t ( ) ; // b a r com f o o } RT (ICS @ UIBK) Programmiermethodik 379/613 Generische Programmierung Generizität Generizität und Vererbung • Abgeleitete Typargumente implizieren nicht abgeleitete generische Typen public class A { . . . } p u b l i c c l a s s B extends A { . . . } ... P a i r <A> pa ; pa = new P a i r <B>(new B ( ) , new B ( ) ) ; // e r r o r • Generischer Typ G1 ist nur dann Subtyp von G2, wenn • Typargumente gleich sind • Rawtype (wird noch besprochen) von G1 ein Subtyp des Rawtypes von G2 ist RT (ICS @ UIBK) Programmiermethodik 380/613 Generische Programmierung Generizität Generizität und Vererbung • Generische Klassen werden bei Vererbung wie gewöhnliche Klassen behandelt (gilt auch für generische Interfaces) • Generische Klasse darf erben • Von nicht generischer Klasse public class MyGen1<T> extends A { ... } • Von konkretisierter generischer Klasse public class MyGen2<T> extends Gen1<Integer> { ... } • Von generischer Klasse mit gleichem Platzhalter public class MyGen3<T> extends Gen2<T> { ... } • Von generischer Klasse mit gleichem Platzhalter und Typebound p u b l i c c l a s s MyGen4<T extends Comparable<T>> extends S o r t e d L i s t <T> { . . . } • Nicht generische Klasse sollte nur von konkretisierter generischer Klasse erben public class B extends Gen3<Integer> { /∗ok ∗/ ... } public class C extends Gen4<T> { /∗not ok ∗/... } RT (ICS @ UIBK) Programmiermethodik 381/613 Generische Programmierung Generizität Generizität und Vererbung • Zuweisungskompatibilität (vorherige Beispiele) • Bei nicht generischer Klasse A a1 = new MyGen1<Integer>(); A a2 = new MyGen1<Double>(); • Bei konkreter generischer Klasse Gen1<Integer> a3 = new MyGen2<Integer>(); Gen1<Integer> a4 = new MyGen2<Double>(); • Bei generischer Klasse müssen aktuelle Typparameter gleich sein Gen2<Integer> a5 = new MyGen3<Integer>(); Gen2<Integer> a6 = new MyGen3<Double>(); //error RT (ICS @ UIBK) Programmiermethodik 382/613 Generische Programmierung Generizität Generizität und Vererbung • Überschreiben bei konkretisierter generischer Klasse • Typparameter werden durch konkrete Typen ersetzt p u b l i c c l a s s M y L i s t extends S o r t e d L i s t <I n t e g e r > { ... public void i n s e r t ( I n t e g e r x ) { . . . } } • Überschreiben bei generischer Klasse • Typparameter bleiben erhalten p u b l i c c l a s s MyList<T extends Comparable<T>> extends S o r t e d L i s t <T> { ... p u b l i c v o i d i n s e r t (T x ) { . . . } } RT (ICS @ UIBK) Programmiermethodik 383/613 Generische Programmierung Generizität Wildcards • Generische Typen können unbestimmtes Typargument nennen • Als Typargument wird Wildcardzeichen ? angegeben (Wildcardtyp) • Alle generischen Typen der gleichen generischen Klasse sind kompatibel zu Wildcardtyp • Beispiel P a i r <?> p ; ... p = new P a i r <I n t e g e r > ( 3 , 2 ) ; p = new P a i r <Double > ( 3 . 0 , 2 . 0 ) ; ... RT (ICS @ UIBK) Programmiermethodik 384/613 Generische Programmierung Generizität Anwendung • Wildcards eignen sich für Situationen, in denen konkretes Typargument keine Rolle spielt public class U t i l { p u b l i c s t a t i c v o i d p r i n t P a i r ( P a i r <?> p a i r ) { System . o u t . p r i n t l n ( p a i r . g e t F i r s t ( ) + " " + p a i r . getSecond ( ) ) ; } ... } ... P a i r <I n t e g e r > p i = new P a i r <I n t e g e r > ( 1 0 , 1 0 ) ; Util . printPair ( pi ); • Wildcardtyp ist ein beliebiger Typ mit unbekannten Eigenschaften • Kann nicht direkt an generische Variable zugewiesen werden Pair<T> p; Pair<?> q; ... q = p; /∗ ok ∗/ p = q; /∗ not ok ∗/ RT (ICS @ UIBK) Programmiermethodik 385/613 Generische Programmierung Generizität Typebounds mit Wildcardtypen • Wildcardtypen können auch mittels Typebounds eingeschränkt werden • Einschränkung von oben mit extends (Upper-Typebound) • Einschränkung von unten mit super (Lower-Typebound) • Für folgende Beispiele wird folgende Hierarchie angenommen: public class A { . . . } p u b l i c c l a s s B extends A { . . . } p u b l i c c l a s s C extends B { . . . } RT (ICS @ UIBK) Programmiermethodik 386/613 Generische Programmierung Generizität Kovarianter Wildcardtyp • Beispiel P a i r <? extends B> pb ; pb = new P a i r <B>(new B ( ) , new B ( ) ) ; // ok pb = new P a i r <C>(new C ( ) , new C ( ) ) ; // ok pb = new P a i r <A>(new A ( ) , new A ( ) ) ; // n o t ok • Allgemein gilt: D<E> ist kompatibel zu D<? extends F>, wenn E zu F kompatibel ist • Benutzung wird eingeschränkt • Schreibende Zugriffe (Methodenaufrufe, die parametrisierten Typ als Parameter enthalten) sind nicht erlaubt • Lesende Zugriffe, die parametrisierten Typ zurückgeben, sind erlaubt RT (ICS @ UIBK) Programmiermethodik 387/613 Generische Programmierung Generizität Kovarianz bei Arrays (Wiederholung) • Kovarianz bei Arrays in Java Object [] s = new String [10]; // ok • Bringt statische Typprüfung des Compilers zu Fall • Beispiel: Number [ ] a = new I n t e g e r [ 2 3 ] ; // ok a [ 0 ] = new Double ( 3 . 1 4 ) ; // ok , b u t r u n t i m e −e x c . • Liefert erst zur Laufzeit ArrayStoreException • Ohne weitere Maßnahmen würde Lücke auch bei kovarianten Wildcardtypen vorhanden sein RT (ICS @ UIBK) Programmiermethodik 388/613 Generische Programmierung Generizität Beispiele für kovarianten Wildcardtyp ... A r r a y L i s t <? extends Number> l i s t ; l i s t = new A r r a y L i s t <I n t e g e r > ( ) ; l i s t = new A r r a y L i s t <Double > ( ) ; l i s t = new A r r a y L i s t <Long > ( ) ; ... l i s t . set (1 , 2.3 d ) ; // n o t ok Number x = l i s t . g e t ( 1 ) ; // ok ... RT (ICS @ UIBK) Programmiermethodik 389/613 Generische Programmierung Generizität Kontravarianter Wildcardtyp • Beispiel P a i r <? super B> pb ; pb = new P a i r <B>(new B ( ) , new B ( ) ) ; // ok pb = new P a i r <C>(new C ( ) , new C ( ) ) ; // n o t ok pb = new P a i r <A>(new A ( ) , new A ( ) ) ; // ok • Allgemein gilt: D<E> ist kompatibel zu D<? super F>, wenn F zu E kompatibel ist • Benutzung wird eingeschränkt • Schreibende Zugriffe sind erlaubt • Lesende Zugriffe sind nicht erlaubt RT (ICS @ UIBK) Programmiermethodik 390/613 Generische Programmierung Generizität Beispiele für kontravarianten Wildcardtyp ... A r r a y L i s t <? super Double> l i s t ; l i s t = new A r r a y L i s t <Number > ( ) ; l i s t = new A r r a y L i s t <Double > ( ) ; l i s t = new A r r a y L i s t <O b j e c t > ( ) ; ... l i s t . set (1 , 2.3 d ) ; // ok Double x = l i s t . g e t ( 1 ) ; // n o t ok ... RT (ICS @ UIBK) Programmiermethodik 391/613 Generische Programmierung Generizität Varianzen (Zusammenfassung) Typ Lesen Schreiben Invarianz C<T> 3 3 Bivarianz C<?> 7 Kovarianz C<? extends B> Kontravarianz C<? super B> ∗ 3 7 ∗ 7 7 3 Kompatible Typargumente T alle B und Unterklassen B und Oberklassen 7 ∗ : Variable vom Typ Object kann jeder Wert zugewiesen werden RT (ICS @ UIBK) Programmiermethodik 392/613 Generische Programmierung Generizität Einsatz von Wildcardtypen • Erlaubt flexiblen Code • Methoden mit Parametern von Wildcardtypen sind möglich • Argumente unterschiedlicher generischer Typen sind möglich • Benötigt Einschränkungen, um statische Prüfung durchzuhalten • Zuweisungen verhindern, die zur Laufzeit Fehler produzieren könnten RT (ICS @ UIBK) Programmiermethodik 393/613 Generische Programmierung Generizität Java 7 – Vereinfachung von Typangaben • Einsatz von Generics erfordert hohen Schreibaufwand • Angabe der Typinformationen bei Deklaration und Erzeugung • Beispiel: P a i r <I n t e g e r , P a i r <S t r i n g , I n t e g e r >> pp = new P a i r <I n t e g e r , P a i r <S t r i n g , I n t e g e r >>(2, p s i ) ; • Schwer zu lesen • Kann mit generischen Fabriksmethoden (siehe kommendes Kapitel Entwurfsmuster) umgangen werden • Ab Java 7 gibt es Diamond-Operator <> für kürze Schreibweise • Compiler wählt korrekten Typ (durch Type-Inference) • Beispiel P a i r <I n t e g e r , P a i r <S t r i n g , I n t e g e r >> pp = new P a i r <>(22, p s i ) ; RT (ICS @ UIBK) Programmiermethodik 394/613 Generische Programmierung Generizität Java 7 – Probleme mit dem Diamond-Operator • Nicht immer funktioniert automatische Type-Inference • Beispiel Set<Number> s = new HashSet <>( A r r a y s . a s L i s t ( 0 L , 0L ) ) ; • Welchen Typ soll der Compiler wählen? • Typ des Ausdrucks auf linken Seite (Set<Number>, d.h. Number)? • Typ des Konstruktorarguments (Long)? • Klare Regel • Compiler überprüft immer zuerst Typ des Konstruktorarguments • Beispiel: Einem Set<Number> kann dann nicht ein HashSet<Long> zugewiesen werden • Beispiel Set<Number> s = new HashSet <>( A r r a y s . a s L i s t ( ( Number ) 0L , 0L ) ) ; RT (ICS @ UIBK) Programmiermethodik 395/613 Generische Programmierung Type-Erasure Übersicht Generische Programmierung Motivation Generizität Type-Erasure Polymorphe Methoden RT (ICS @ UIBK) Programmiermethodik 396/613 Generische Programmierung Type-Erasure Homogene bzw. Heterogene Übersetzung • Es gibt zwei Realisierungsmöglichkeiten für generische Datentypen • Heterogene Variante • Für jedes Typargument (etwa String, Integer , Point usw.) wird individueller Code erzeugt, also drei Klassen (String−Stack, Integer −Stack, Point−Stack usw.) • Beispiel: C++ Homogene Übersetzung • Für jede parametrisierte Klasse wird eine Klasse erzeugt, die statt generischen Typs allgemeine Klasse (wie z.B. Object) einsetzt • Für konkreten Typ werden Typanpassungen in Anweisungen eingebaut • Beispiel: Java RT (ICS @ UIBK) Programmiermethodik 397/613 Generische Programmierung Type-Erasure Type-Erasure • Mechanismus hinter Übersetzung generischer Klassen etc. wird als Type-Erasure bezeichnet • Generics (und deren Anwendungen) werden in 2 Schritten übersetzt • Type-Erasure reduziert generischer Code auf normalen, nicht generischen Java-Quelltext • Dieser Quelltext wird normal weiterverarbeitet (wie bisher) • Generics werden nur vom Compiler verarbeitet • Laufzeitsystem (und JVM) sehen nichts davon • Bei generischen Klassen werden im Zuge der Type-Erasure • Typvariablen in spitzen Klammern gelöscht, • Vorkommen von Typvariablen mit einem oder mehreren Typebounds durch den einzigen bzw. erstgenannten Typebound ersetzt, • Vorkommen von Typvariablen ohne Typebound durch Object ersetzt (Default-Typebound) RT (ICS @ UIBK) Programmiermethodik 398/613 Generische Programmierung Type-Erasure Beispiel • Vor Type-Erasure p u b l i c c l a s s P a i r <T> { private T f i r s t ; private T second ; p u b l i c P a i r (T f i r s t , T l a s t ) { . . . } ... } • Nach Type-Erasure public class Pair { private Object f i r s t ; private Object second ; public Pair ( Object f i r s t , Object l a s t ) { . . . } ... } RT (ICS @ UIBK) Programmiermethodik 399/613 Generische Programmierung Type-Erasure Type-Erasure bei generischen Typen • Zuerst statische Typprüfung • Typargumente müssen, falls angegeben, allen Typebounds genügen • Generische Typen müssen untereinander korrekt verwendet werden • Danach Type-Erasure • Typargumente in spitzen Klammern löschen, inklusive Wildcards • Typecasts einfügen, wenn Wert des Typarguments benutzt wird • Vor Type-Erasure P a i r <I n t e g e r > p = new P a i r <I n t e g e r > ( 1 , 1 ) ; Integer i = p. getFirst (); • Nach Type-Erasure P a i r p = new P a i r ( 1 , 1 ) ; Integer i = ( Integer ) p. getFirst (); RT (ICS @ UIBK) Programmiermethodik 400/613 Generische Programmierung Type-Erasure Type-Erasure (Zusammenfassung) • Alle generischen Typen teilen sich eine einzige Implementierung ihrer Klasse • Zur Laufzeit existieren keine • • • • Typvariablen Typargumente Typebounds Wildcards RT (ICS @ UIBK) Programmiermethodik 401/613 Generische Programmierung Type-Erasure Rawtypes • Durch Type-Erasure reduzierte Definition liefert sogenannten Rawtype der generischen Klasse • Es gibt genau einen Rawtype zu einer generischen Klasse • Ist normale, nicht-generische Klasse • Kann verwendet werden, z.B. Pair p = new Pair(10,10) • Vorteil • Alte Applikationen (vor Java 1.5) können mit generischen Klassen zusammenarbeiten • Nachteil • Keine statische Prüfung • Warnungen RT (ICS @ UIBK) Programmiermethodik 402/613 Generische Programmierung Type-Erasure Grenzen generischer Typen in Java • Statische Elemente • Statische Datenelemente und statische Methoden einer generischen Klasse können keine Typvariablen der Klasse benutzen • Dynamische Typprüfung • Typvariable kann nicht mit Operator instanceof überprüft werden if (x instanceof T) ... • Compiler kann beim Übersetzen noch nicht den Typ kennen • Type-Erasure würde Bedingung auf sinnlosen Test if (x instanceof Object) ... reduzieren • Test auf Rawtypes möglich i f ( x i n s t a n c e o f P a i r ) . . . // ok i f ( x i n s t a n c e o f P a i r <I n t e g e r >) . . . // n o t ok RT (ICS @ UIBK) Programmiermethodik 403/613 Generische Programmierung Type-Erasure Grenzen generischer Typen in Java • Typecasts p u b l i c c l a s s S t o r e <T> { private T info ; public void s e t I n f o ( Object x ){ i n f o = (T) x ; // Warnung , p r o b l e m a t i s c h } public T getInfo (){ return i n f o ; } } .. S t o r e <S t r i n g > s t = new S t o r e <S t r i n g > ( ) ; s t . s e t I n f o ( 2 3 ) ; // k e i n e Warnung S t r i n g s = s t . g e t I n f o ( ) ; // b e i A u s f u e h r u n g // C l a s s C a s t E x c e p t i o n RT (ICS @ UIBK) Programmiermethodik 404/613 Generische Programmierung Type-Erasure Grenzen generischer Typen in Java • Konstruktoren • Wegen fehlenden Information über spätere Typargumente können in generischer Klasse keine Konstruktoren von Typvariablen aufgerufen werden (T kann auch nicht als Basisklasse verwendet werden) p u b l i c c l a s s S t o r e <T> { private T info ; public Store () { i n f o = new T ( ) ; // n o t ok } ... } p u b l i c c l a s s S t o r e <T> { private T info ; public Store () { i n f o = n u l l ; // ok } ... } RT (ICS @ UIBK) Programmiermethodik 405/613 Generische Programmierung Type-Erasure Grenzen generischer Typen in Java • Arrays von Typvariablen können nicht angelegt werden p u b l i c c l a s s C o n t a i n e r <T> { p r i v a t e T [ ] a = new T [ 1 0 0 ] ; ... } // c o m p i l e e r r o r • Um trotzdem mit Arrays zu arbeiten p u b l i c c l a s s C o n t a i n e r <T> { p r i v a t e T [ ] a = (T [ ] ) new O b j e c t [ 1 0 0 ] ; ... } • Kovarianz von Arraytypen ausnutzen • Code wird mit Warnung übersetzt und statische Typprüfung wird unterlaufen • Annotation @SuppressWarnings("unchecked") vor entsprechender Klasse benutzen • Man muss korrekte Zugriffsmethoden implementieren, die nur T-Objekte im Array ablegen können RT (ICS @ UIBK) Programmiermethodik 406/613 Generische Programmierung Type-Erasure Grenzen generischer Typen in Java • Arrays von parametrisierten Typen werden nicht zugelassen • Beispiel: Comparable<String>[] ist nicht erlaubt • Grund: Programme wären nicht typsicher: Nach fehlerfreien Übersetzung könnte es noch immer zu unerwarteter ClassCastException kommen (also ohne expliziten Cast) • Beispiel • Folgender Code muss zur Übersetzungszeit unterbunden werden P a i r <I n t e g e r > [ ] p a r r = new P a i r <I n t e g e r > [ 9 ] ; // e r r o Object [ ] a r r = parr ; a r r [ 0 ] = new P a i r <S t r i n g >("a" , "b" ) ; Zur Laufzeit keine ArrayStoreException wegen Type-Erasure • Zulässig ist aber O b j e c t [ ] a r r = new P a i r <? >[9]; a r r [ 0 ] = new P a i r <S t r i n g >("a" , "b" ) ; Aber: P a i r <S t r i n g > p = a r r [ 0 ] ; // e r r o r p = ( P a i r <S t r i n g >) a r r [ 0 ] ; // w a r n i n g RT (ICS @ UIBK) Programmiermethodik 407/613 Generische Programmierung Type-Erasure Grenzen generischer Typen in Java • Ausnahmen • Es ist nicht erlaubt, parametrisierten Typ direkt oder indirekt von Throwable abzuleiten ⇒ parametrisierte Exception-Typen sind nicht erlaubt • Exception-Handling-Mechanismus ist Laufzeit-Mechanismus • Laufzeitsystem (JVM) weiß nichts von Java Generics • Class-Literal • Man kann von parametrisiertem Typ kein Class-Literal bilden • Ausdruck wie z.B. LinkedList <String>.class ist unzulässig • In Java gibt es keine exakte Laufzeitrepräsentation eines parametrisierten Typs • Der Laufzeittyp ist immer nur der nicht parametrisierte Rawtype (im Beispiel LinkedList ) RT (ICS @ UIBK) Programmiermethodik 408/613 Generische Programmierung Type-Erasure Brückenmethoden • Spezielle Situationen müssen vom Compiler selbst aufgelöst werden • Programmierer muss sich keine Gedanken machen • Besonderes Beispiel sind Brückenmethoden • Brückenmethoden werden eingefügt, wenn Klasse von parametrisierbarem Typ (Klasse, Interface) abgeleitet wird RT (ICS @ UIBK) Programmiermethodik 409/613 Generische Programmierung Type-Erasure Beispiel p u b l i c c l a s s O<T> { p u b l i c i n t g e t (T param ) { return 5; } } p u b l i c c l a s s U extends O<S t r i n g > { @Override p u b l i c i n t g e t ( S t r i n g param ) { return 10; } } • Was passiert nach Type-Erasure? • Haben get-Methoden gleiche Signatur? • Wird hier noch überschrieben? RT (ICS @ UIBK) Programmiermethodik 7 3 410/613 Generische Programmierung Type-Erasure Beispiel nach Type-Erasue public class O { p u b l i c i n t g e t ( O b j e c t param ) { return 5; } } p u b l i c c l a s s U extends O { p u b l i c i n t g e t ( S t r i n g param ) { return 10; } // Brueckenmethode e i n g e f u e g t p u b l i c i n t g e t ( O b j e c t param ) { r e t u r n g e t ( ( S t r i n g ) param ) ; } } RT (ICS @ UIBK) Programmiermethodik 411/613 Generische Programmierung Type-Erasure Brückenmethode im vorherigen Beispiel • Brückenmethode (2. get-Methode in U) wurde vom Compiler eingefügt • Überschreibt Methode der Klasse O und ruft jetzt die theoretisch überschreibende Methode der Klasse U auf • Klasse U verhält sich so, als wäre Methode überschrieben worden • Programmierer merkt davon nichts • Nur im Bytecode ersichtlich • Nachfolgende Decompilierung zeigt das auch • Brückenmethoden werden auch bei Methoden verwendet, die sich nach Type-Erasure nur im Rückgabewert unterscheiden RT (ICS @ UIBK) Programmiermethodik 412/613 Generische Programmierung Type-Erasure Brückenmethoden bei Rückgabewerten: Vorher p u b l i c i n t e r f a c e I t e r a t o r <E> { p u b l i c boolean h a s N e x t ( ) ; public E next ( ) ; } public class Alphabet implements I t e r a t o r <C h a r a c t e r > { p r i v a t e char c u r r e n t = ’A’ ; p u b l i c boolean h a s N e x t ( ) { r e t u r n t h i s . c u r r e n t <= ’Z’ ; } public Character next () { r e t u r n new C h a r a c t e r ( t h i s . c u r r e n t ++); } } RT (ICS @ UIBK) Programmiermethodik 413/613 Generische Programmierung Type-Erasure Brückenmethoden bei Rückgabewerten: Nachher public interface I t e r a t o r { p u b l i c boolean h a s N e x t ( ) ; public Object next ( ) ; } p u b l i c c l a s s A l p h a b e t implements I t e r a t o r { p r i v a t e char c u r r e n t = ’A’ ; p u b l i c boolean h a s N e x t ( ) { r e t u r n c u r r e n t <= ’Z’ ; } public Character next () { r e t u r n new C h a r a c t e r ( c u r r e n t ++); } // d o p p e l t e s n e x t ( ) n i c h t i n J a v a m o e g l i c h public Object next () { return next ( ) ; } } RT (ICS @ UIBK) Programmiermethodik 414/613 Generische Programmierung Polymorphe Methoden Übersicht Generische Programmierung Motivation Generizität Type-Erasure Polymorphe Methoden RT (ICS @ UIBK) Programmiermethodik 415/613 Generische Programmierung Polymorphe Methoden Polymorphe Methoden • Generische Methoden werden als polymorphe Methoden bezeichnet • Sind unabhängig von generischen Typen • Können in nicht-generischen Klassen definiert und aufgerufen werden • Auch Konstruktoren und statische Methoden können polymorph sein • Beim Aufruf muss immer explizit Zielobjekt angegeben werden (gegebenenfalls auch this, bei statischen Methoden muss Klasse angegeben werden) RT (ICS @ UIBK) Programmiermethodik 416/613 Generische Programmierung Polymorphe Methoden Beispiel public class Voter { p u b l i c s t a t i c <T> T v o t e (T x , T y , T z ) { i f (x . equals (y )) { return x ; } i f (y . equals ( z )) { return y ; } i f ( z . equals (x )) { return x ; } return n u l l ; } } ... S t r i n g s = V o t e r .< S t r i n g > v o t e ( " ATEST " , "TEST" , " ATEST " ) ; // S t r i n g s = V o t e r .< S t r i n g > v o t e ( "ATEST" , "TEST " , 1 ) ; System . o u t . p r i n t l n ( s ) ; // ATEST RT (ICS @ UIBK) Programmiermethodik 417/613 Generische Programmierung Polymorphe Methoden Typebounds • Auch bei polymorphen Methoden können Typebounds verwendet werden • Beispiel • Methode median soll von drei Werten den Median zurückgeben p u b l i c <T extends Comparable <? super T>> T median (T x , T y , T z ) { i n t c x y = x . compareTo ( y ) ; i f ( c x y == 0 ) { return x ; } i f ( cxy < 0) . . . } • Erlaubter Aufruf: Integer i = v.<Integer>median(3,2,5); • Nicht erlaubt: Object i = v.<Object>median(3,2,5); RT (ICS @ UIBK) Programmiermethodik 418/613 Generische Programmierung Polymorphe Methoden Type-Inference • In vielen Fällen können konkrete Typargumente beim Aufruf einer polymorphen Methode weggelassen werden • Compiler erkennt aus dem Kontext durch Type-Inference die korrekten Typargumente • Funktioniert auch über mehrere Stufen (verschachtelte Methodenaufrufe) hinweg • Beispiel (voriges Beispiel) System . o u t . p r i n t l n ( V o t e r . v o t e ( " ATEST " , " TEST " , " ATEST " ) ) ; System . o u t . p r i n t l n ( V o t e r . v o t e ( " ATEST " , " TESTC " , V o t e r . v o t e ( " TESTA " , " TESTC " , " TESTC " ) ) ) ; RT (ICS @ UIBK) Programmiermethodik 419/613 Generische Programmierung Polymorphe Methoden Gemischte Typargumente • Werden bei polymorpher Methode Argumente mit unterschiedlichen Typen für gleiche Typvariable verwendet: • Type-Inference fällt auf den nähesten gemeinsamen Basistyp zurück • Beispiel mit polymorpher Methode vote • Möglich: Object n = Voter.vote(1, 1, "1"); • Nicht möglich: Integer n = Voter.vote(1, 1, "1"); RT (ICS @ UIBK) Programmiermethodik 420/613 Generische Programmierung Polymorphe Methoden Polymorphe Methoden und Überladen • Normale Methode darf nicht so definiert werden, dass sie nach Type-Erasure mit polymorpher Methode kollidiert • Unzulässig p u b l i c <T> T v o t e (T x , T y , T z ) public Object vote ( Object x , Object y , Object z ) • Zulässig p u b l i c <T extends Comparable <? super T>> T median (T x , T y , T z ) { . . . } p u b l i c I n t e g e r median ( Integer x , Integer y , Integer z) { . . . } • Beim Aufruf überladener Methoden werden polymorphe Methoden erst dann berücksichtigt, wenn keine normalen Methoden passen RT (ICS @ UIBK) Programmiermethodik 421/613 Generische Programmierung Polymorphe Methoden Varargs und Generics • Varargs und Generics können zusammen verwendet werden • Im JDK findet man zahlreiche Beispiele dafür • Es kann aber zu Problemen kommen • Beispiel: Polymorphe varargs-Methode p r i v a t e s t a t i c <T> L i s t <T> a s L i s t (T . . . e l e m e n t s ) { L i s t <T> l i s t = new L i n k e d L i s t <T> ( ) ; f o r (T t : e l e m e n t s ) { l i s t . add ( t ) ; } return l i s t ; } • Übersetzt ohne Fehler und ohne Warning (bis Java 1.6) • Aufruf der Methode (Beispiel mit Pair<String>) ist aber problematisch P a i r <S t r i n g > a , b , c ; ... L i s t <P a i r <S t r i n g >> l i s t = a s L i s t ( a , b , c ) ; RT (ICS @ UIBK) Programmiermethodik 422/613 Generische Programmierung Polymorphe Methoden Varargs und Generics • Problem im Beispiel auf vorherigenr Folie • Compiler erzeugt aus variabler Argumentliste ein Array • Wenn Aufrufargumente von parametrisiertem Typ sind, dann produziert der Compiler eine unchecked-Warnung • Parametrisierter Typ (wie Pair<String>) hat aufgrund der Type-Erasure im Byte-Code keine exakte Darstellung • In Java sind normalerweise Arrays mit Elementen eines parametrisierten Typs unzulässig (siehe Folie 407) • In diesem Fall gibt es aber nur Warnung bei Verwendung der Methode • Java 7 • Compiler erzeugt nun schon Warnung bei Definition der Methode (deutet eine sogenannte Heap-Pollution an) • Kann mit Annotation unterdrückt werden RT (ICS @ UIBK) Programmiermethodik 423/613 Java Collection Framework Übersicht Java Collection Framework Einleitung Ausgewählte Klassen Iteratoren Weiteres Wissenswertes RT (ICS @ UIBK) Programmiermethodik 424/613 Java Collection Framework Einleitung Übersicht Java Collection Framework Einleitung Ausgewählte Klassen Iteratoren Weiteres Wissenswertes RT (ICS @ UIBK) Programmiermethodik 425/613 Java Collection Framework Einleitung Motivation • Programmierer benötigt sehr oft bestimmte Datenstrukturen • Datenstrukturen sollten schon vorhanden sein • Datenstrukturen sollten generisch sein • Allgemeine Algorithmen (anwendbar auf unterschiedliche Datenstrukturen) sollten vorhanden sein • Lösung? • Java Collection-Framework RT (ICS @ UIBK) Programmiermethodik 426/613 Java Collection Framework Einleitung Grundlagen • Collection-Framework befindet sich im Paket java . util • Für unterschiedliche Datenstrukturen stehen unterschiedliche Interfaces zur Verfügung • Interfaces geben Schnittstellen für Zugriff auf Datenstrukturen an • Konkrete Verwaltung wird durch konkrete Implementierungen dieser Interfaces bestimmt • Seit Java 1.5: Collection-Framework ist generisch • Jedes Interface kann durch unterschiedliche Implementierungen unterstützt werden • Es gibt polymorphe Algorithmen, die auf Collection-Objekte (Listen etc.) angewandt werden können RT (ICS @ UIBK) Programmiermethodik 427/613 Java Collection Framework Einleitung Interfaces (Überblick) • Interfaces sind die Grundlage • Applikationen sollten ihren Code ausschließlich auf Interfaces aufbauen • Interfaces bilden Hierarchien Map Collection Set List Queue SortedMap SortedSet RT (ICS @ UIBK) Programmiermethodik 428/613 Java Collection Framework Einleitung Collection-Interfaces (Seit Java 1.5) • Collection • Collection verwaltet Objekte (Elemente) • Interface enthält generelle Methoden (für alle Collection -Typen) • Es gibt keine direkte Implementierung dieses Interfaces • Set • Collection ohne Duplikate (bzgl. equals) • List • Geordnete Collection (mit Duplikaten) • Elemente können über einen Index angesprochen werden (nicht immer effizient) • Queue • Verwaltung von Warteschlangen (ähnlich zu Listen) • FIFO, Prioritätswarteschlangen • Map • Maps verwalten Schlüssel mit dazugehörigen Werten • zu jedem Schlüssel maximal ein Eintrag • SortedSet und SortedMap • verwalten Elemente / Schlüssel in sortierter aufsteigender Reihenfolge RT (ICS @ UIBK) Programmiermethodik 429/613 Java Collection Framework Einleitung Implementierung • Unterschiedliche Ansätze bei der Implementierung von konkreten Collection-Klassen • Generelle Implementierungen, die häufig in Applikationen verwendet werden • Spezielle Implementierungen • Nebenläufige Implementierungen (für Multithreaded-Applikationen, siehe Entwurf von Softwaresystemen) • Wrapper-Implementierungen, die mit anderen Implementierungen benutzt werden (oft generelle Implementierungen) und zusätzliche oder eingeschränkte Funktionalität zur Verfügung stellen • Einfache effiziente Implementierungen (Mini-Implementierungen) für spezielle Collections • Abstrakte Implementierungen, die Implementierungsskelett zur Verfügung stellen und damit Implementierung eigener Collection-Klassen erleichtern RT (ICS @ UIBK) Programmiermethodik 430/613 Java Collection Framework Einleitung Generelle Implementierungen Interface Set Hash-Tabellen Dynamische Arrays Bäume Verkette Liste Hash-Tabelle + Verkettete Liste HashSet RT (ICS @ UIBK) List Queue Map HashMap ArrayList TreeSet TreeMap LinkedList Linked HashSet Programmiermethodik LinkedList Linked HashMap 431/613 Java Collection Framework Einleitung Generelle Implementierungen • Es gibt generelle Implementierungen für Interfaces Set, List und Map • Interfaces SortedSet und SortedMap werden von TreeSet bzw. TreeMap zusätzlich implementiert • Queue-Interface wird z.B. von den folgenden Klassen implementiert • LinkedList : FIFO Warteschlangen • PriorityQueue: Prioritätswarteschlange (ist eher eine spezielle Implementierung) RT (ICS @ UIBK) Programmiermethodik 432/613 Java Collection Framework Einleitung Erweiterungen bei Java 1.6 • Deque (Double ended queue) • Einfügen und Löschen an beiden Enden • Wird u.a. von der Klasse LinkedList implementiert • NavigableSet und NavigableMap • Sollen SortedSet und SortedMap ersetzen • Sind Erweiterungen, die Navigieren (aufsteigend, absteigend) erlauben • Zusätzliche nebenläufige Implementierungen • Zusätzliche Hilfsmethoden RT (ICS @ UIBK) Programmiermethodik 433/613 Java Collection Framework Ausgewählte Klassen Übersicht Java Collection Framework Einleitung Ausgewählte Klassen Iteratoren Weiteres Wissenswertes RT (ICS @ UIBK) Programmiermethodik 434/613 Java Collection Framework Ausgewählte Klassen Eigenschaften ausgewählter Klassen • ArrayList • Indexzugriff auf Elemente überall schnell (O(1)) • Einfügen und Löschen am Listenende schnell (amortisiert: O(1)) und mit wachsender Entfernung vom Listenende langsamer (O(n)) • LinkedList • Indexzugriff auf Elemente an Enden schnell (O(1)) und zur Mitte hin langsamer (O(n)) • Einfügen und Löschen ohne Indexzugriff überall gleich schnell (O(1)) • Ansonsten abhängig vom Indexzugriff (O(n)) • HashSet • null-Elemente zulässig • Auf Elementen muss hashCode sinnvoll definiert sein • Einfügen, Suchen und Löschen immer gleich schnell (O(1)) • Achtung bei Rehashing (siehe API-Beschreibung) • TreeSet • null-Elemente nicht erlaubt • Auf Elementen eines TreeSets muss Ordnung definiert sein (d.h. Interface Comparable<T> implementieren) • Geschwindigkeit von Einfügen, Suchen und Löschen: O(log(n)) RT (ICS @ UIBK) Programmiermethodik 435/613 Java Collection Framework Ausgewählte Klassen Methoden (Beispiele, E ist Elementtyp) // i n C o l l e c t i o n int size () boolean add ( E e ) boolean a d d A l l ( C o l l e c t i o n <? extends E> c ) boolean remove ( O b j e c t o ) boolean r e m o v e A l l ( C o l l e c t i o n <?> c ) boolean r e t a i n A l l ( C o l l e c t i o n <?> c ) boolean c o n t a i n s ( O b j e c t o ) boolean c o n t a i n s A l l ( C o l l e c t i o n <?> c ) // i n L i s t E get ( int i ) E set ( int i , E t ) int indexOf ( Object o ) E remove ( i n t i ) boolean a d d A l l ( i n t i , C o l l e c t i o n <? extends E> c ) RT (ICS @ UIBK) Programmiermethodik 436/613 Java Collection Framework Ausgewählte Klassen Beispiel import j a v a . u t i l . ∗ ; L i s t <I n t e g e r > i l = new A r r a y L i s t < >(); f o r ( i n t x = 1 ; x < 1 0 ; x++) { i l . add ( x ) ; } System . o u t . p r i n t l n ( i l ) ; // [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] System . o u t . p r i n t l n ( i l . g e t ( 3 ) ) ; // 4 System . o u t . p r i n t l n ( i l . s i z e ( ) ) ; // 9 System . o u t . p r i n t l n ( i l . remove ( 2 ) ) ; // 3 System . o u t . p r i n t l n ( i l ) ; // [ 1 , 2 , 4 , 5 , 6 , 7 , 8 , 9 ] System . o u t . p r i n t l n ( i l . c o n t a i n s ( 7 ) ) ; // t r u e System . o u t . p r i n t l n ( i l . s e t ( 5 , 2 2 ) ) ; System . o u t . p r i n t l n ( i l ) ; // [ 1 , 2 , 4 , 5 , 6 , 2 2 , 8 , 9 ] System . o u t . p r i n t l n ( i l . i n d e x O f ( 2 2 ) ) ; // 5 RT (ICS @ UIBK) Programmiermethodik 437/613 Java Collection Framework Ausgewählte Klassen Maps • Arrays und Collections speichern einzelne Werte des Elementtyps (über Indexwerte adressiert, Typ der Indexwerte ist int) • Maps sind Verallgemeinerung von Arrays mit beliebigem Indextyp • Beispiel Telefonbuch • Name mit Telefonnummer verknüpft. • Indextyp ist daher String (Name) • Map-Eintrag hat • Schlüssel (key) • Wert (value) RT (ICS @ UIBK) Programmiermethodik 438/613 Java Collection Framework Ausgewählte Klassen Maps (key-value) • Jedem Schlüssel ist genau ein Wert zugeordnet • Map ist Menge von Schlüssel-Werte Paaren • Schlüssel müssen innerhalb einer Map eindeutig sein • Werte müssen nicht eindeutig sein • Wie bei Sets gibt es grundsätzlich zwei Versionen • HashMap • Ungeordnet • Mittels Hashing implementiert • TreeMap • Geordnet • Rot-Schwarz-Baum (balanciert) • Methoden wie put, get, containsKey, containsValue, remove etc. werden angeboten RT (ICS @ UIBK) Programmiermethodik 439/613 Java Collection Framework Ausgewählte Klassen Beispiel import j a v a . u t i l . ∗ ; import s t a t i c j a v a . l a n g . System . o u t ; Map<S t r i n g , Double> w i s h l i s t = new HashMap < >(); w i s h l i s t . p u t ( " Handy " , 1 9 9 . 9 9 ) ; w i s h l i s t . p u t ( " Book " , 1 3 . 9 9 ) ; w i s h l i s t . p u t ( " Friend " , Double . NaN ) ; out . p r i n t l n ( w i s h l i s t ) ; // { Book =13.99 , F r i e n d=NaN , Handy =199.99} o u t . p r i n t l n ( w i s h l i s t . g e t ( " Book " ) ) ; // 1 3 . 9 9 o u t . p r i n t l n ( w i s h l i s t . c o n t a i n s K e y ( " Friend " ) ) ; // t r u e o u t . p r i n t l n ( w i s h l i s t . remove ( " Handy " ) ) ; // 1 9 9 . 9 9 o u t . p r i n t l n ( w i s h l i s t ) ; // {Book =13.99 , F r i e n d=NaN} RT (ICS @ UIBK) Programmiermethodik 440/613 Java Collection Framework Ausgewählte Klassen Maps (equals, hashCode) • HashMap und andere Klassen des Collection-Frameworks rufen Methode equals auf, um Gleichheit von Schlüsselobjekten / Elementen festzustellen • Von einigen Klassen wird Methode hashCode verwendet • Daher sollten alle Schlüssel/Element-Klassen die Methoden equals und hashCode überschreiben • Von Klasse Object geerbte Versionen dieser Methoden sind selten ausreichend (nur Referenzgleichheit) RT (ICS @ UIBK) Programmiermethodik 441/613 Java Collection Framework Ausgewählte Klassen Maps und Collections • Maps implementieren nicht Interface Collection , sind aber Teil des Collection-Frameworks • Maps und Collections können verknüpft werden (hier: Map<K,V>) • Methode keySet liefert Menge aller Schlüssel einer Map als Set<K> • Methode values liefert Menge aller Werte als Collection <V> • Methode entrySet liefert Menge aller Einträge als Set<Map.Entry<K,V>> • Map.Entry<K,V> definiert Methoden K getKey() und V getValue() • Maps kennen keine Iteratoren, Sets und Collections hingegen schon ⇒ Man kann auf diesem Wege über Maps iterieren • Über Organisation von keySet, values, entrySet ist nichts bekannt RT (ICS @ UIBK) Programmiermethodik 442/613 Java Collection Framework Ausgewählte Klassen Maps und Collections • Methoden keySet, values und entrySet erzeugen keine neue Collection • Sie liefern sogenannte Sichten (views) • Daher sind diese Methoden auch bei großen Datenmengen effizient • Es werden keine Daten kopiert • Sichten greifen direkt auf zugrunde liegende Map zu • Änderungen an Sichten wirken sich auf darunterliegende Map aus und umgekehrt ⇒ Wird Map geändert, dann wirkt sich das auf alle Sichten aus RT (ICS @ UIBK) Programmiermethodik 443/613 Java Collection Framework Ausgewählte Klassen Beispiel import s t a t i c j a v a . l a n g . System . ∗ ; import j a v a . u t i l . ∗ ; Map<S t r i n g , Double> w i s h l i s t = new HashMap < >(); w i s h l i s t . p u t ( " Handy " , 1 9 9 . 9 9 ) ; w i s h l i s t . p u t ( " Book " , 1 3 . 9 9 ) ; w i s h l i s t . p u t ( " Friend " , Double . NaN ) ; Set<S t r i n g > w i s h e s = w i s h l i s t . k e y S e t ( ) ; o u t . p r i n t l n ( w i s h e s ) ; // [ Book , F r i e n d , Handy ] w i s h l i s t . remove ( " Book " ) ; o u t . p r i n t l n ( w i s h e s ) ; // [ F r i e n d , Handy ] w i s h e s . remove ( " Friend " ) ; o u t . p r i n t l n ( w i s h l i s t ) ; // { Handy =199.99} RT (ICS @ UIBK) Programmiermethodik 444/613 Java Collection Framework Iteratoren Übersicht Java Collection Framework Einleitung Ausgewählte Klassen Iteratoren Weiteres Wissenswertes RT (ICS @ UIBK) Programmiermethodik 445/613 Java Collection Framework Iteratoren Iteratoren allgemein • Iteratoren sind Verallgemeinerung von Indexwerten • Werden ähnlich wie Indexwerte verwendet, aber innerer Aufbau bleibt verborgen • Alle Iteratoren implementieren generisches Interface Iterator <T> • Iteratoren haben gleichen Elementtyp wie zugrunde liegende Collection • Iterator wird durch eine Methode (z.B. iterator ()) angeboten • Iterator bietet folgende Methoden an • hasNext: testet, ob es weitere Elemente gibt (true) oder nicht (false ) • next: liefert nächstes Element und rückt Iterator gleichzeitig weiter, d.h. aufeinanderfolgende Aufrufe von next liefern immer neue Elemente • remove: entfernt zuletzt zurückgegebenes Element (optional, d.h. wirft evtl. UnsupportedOperationException) RT (ICS @ UIBK) Programmiermethodik 446/613 Java Collection Framework Iteratoren Eigenschaften von Iteratoren • Iterator läuft von Beginn an Element für Element durch Collection (keine Sprünge, kein Start an beliebiger Stelle) • Iterator steht immer zwischen zwei Elementen (oder vor erstem, nach letztem) • Iterator ist verbraucht, wenn er am Ende angekommen ist (keine Wiederverwendung) • Für neuen Durchlauf muss neuer Iterator erzeugt werden • Innerhalb einer Collection können gleichzeitig mehrere Iteratoren unterwegs sein • Mehrere Iteratoren sind unabhängig voneinander und können einzeln bewegt werden RT (ICS @ UIBK) Programmiermethodik 447/613 Java Collection Framework Iteratoren Beispiel: Iterator von Listen ... L i s t <S t r i n g > l s = new L i n k e d L i s t <S t r i n g > ( ) ; l s . add ( "A" ) ; l s . add ( "B" ) ; l s . add ( "A" ) ; l s . add ( "B" ) ; ... I t e r a t o r <S t r i n g > i s = l s . i t e r a t o r ( ) ; while ( i s . hasNext ( ) ) { String s = i s . next ( ) ; i f ( s . e q u a l s ( "A" ) ) i s . remove ( ) ; } System . o u t . p r i n t l n ( l s ) ; // [ B B ] RT (ICS @ UIBK) Programmiermethodik 448/613 Java Collection Framework Iteratoren Beispiel: Iterator von Maps Map<S t r i n g , Double> m = new HashMap<S t r i n g , Double > ( ) ; m. p u t ( "PC1" , 1 1 9 9 . 9 0 ) ; m. p u t ( "PC2" , 1 9 9 9 . 9 0 ) ; m. p u t ( "PC3" , 9 8 0 . 0 0 ) ; System . o u t . p r i n t l n (m) ; // {PC3 =980.0 , PC1 =1199.9 , PC2=1999.9} I t e r a t o r <Map . E n t r y <S t r i n g , Double>> i m e s ; i m e s = m. e n t r y S e t ( ) . i t e r a t o r ( ) ; while ( imes . hasNext ( ) ) { Map . E n t r y <S t r i n g , Double> i t e m = i m e s . n e x t ( ) ; i f ( item . getValue ( ) < 1500) { System . o u t . p r i n t l n ( i t e m . g et Ke y ( ) ) ; // PC3 , PC1 } } // b e i LinkedHashMap / S e t w i r d i n R e i h e n f o l g e // d e s E i n f u e g e n s i t e r i e r t RT (ICS @ UIBK) Programmiermethodik 449/613 Java Collection Framework Iteratoren Listen-Iteratoren • Für Listen gibt noch eigene Iteratoren • Diese implementieren Interface ListIterator <T> • Listen-Iterator kann sich vorwärts und rückwärts bewegen • Zusätzlich zu den Methoden von Iterator werden zum Beispiel angeboten: • previous und hasPrevious, die sich auf vorhergehendes Element beziehen • previousIndex und nextIndex liefern Indexwerte des vorhergehenden und nächsten Elements • Listen-Iterator ist nicht verbraucht, wenn er am Ende der Liste angekommen ist RT (ICS @ UIBK) Programmiermethodik 450/613 Java Collection Framework Iteratoren Modifikation und Iteratoren • Wird Collection modifiziert (z.B. neues Element eingefügt), dann werden alle Iteratoren ungültig • Beim nächsten Zugriffsversuch auf Iterator nach Änderung wirft dieser ConcurrentModificationException • Wird als fail-fast bezeichnet • Iterator gerät nicht irgendwann in inkonsistenten Zustand • Iterator wird sofort unbrauchbar gemacht • Iteratoren reagieren nur auf strukturelle Änderungen, d.h. Ersetzen eines Elements verändert Struktur nicht und lässt Iteratoren intakt RT (ICS @ UIBK) Programmiermethodik 451/613 Java Collection Framework Iteratoren Modifikation und Iteratoren • Iteratoren bieten selbst Änderungsoperationen an, bei denen der betreffende Iterator funktionsfähig bleibt • Alle Iteratoren definieren Methode remove, die das zuletzt überquerte Element aus Collection entfernt • Aber • Iterator muss sich zuerst bewegen, dann erst kann remove aufgerufen werden • Nach einem Aufruf muss erst weiteres Element überquert werden • Bei Listen-Iteratoren ist zuletzt überquertes Element abhängig von Laufrichtung (kann vom Listenanfang aus gesehen vor oder hinter dem Iterator sein) • Bei Struktur-Änderungen mittels Iterator bleibt dieser Iterator intakt • Andere Iteratoren, die in gleicher Collection unterwegs sind, werden ungültig RT (ICS @ UIBK) Programmiermethodik 452/613 Java Collection Framework Iteratoren Modifikation bei Listen-Iteratoren • Bei Listen-Iteratoren gibt es neben remove noch zusätzliche Methoden • add: fügt Element in der Lücke ein, in der der Iterator steht • set: ersetzt zuletzt überquertes Element durch übergebenes Element RT (ICS @ UIBK) Programmiermethodik 453/613 Java Collection Framework Iteratoren foreach-Schleife • So wie Arrays können auch Collections mit foreach-Schleife durchlaufen werden • Beispiel L i s t <I n t e g e r > i l = new A r r a y L i s t < >(); ... i n t sum = 0 ; for ( Integer i : i l ) sum += i ; } • foreach-Schleifen arbeiten wie Iteratoren • Änderung der Collection während des Durchlaufens führt zur Ausnahme • Implementiert Klasse das Interface Iterable <T>, dann können Objekte dieser Klasse mit foreach-Schleife durchlaufen werden i n t e r f a c e I t e r a b l e <T> { I t e r a t o r <T> i t e r a t o r ( ) ; } RT (ICS @ UIBK) Programmiermethodik 454/613 Java Collection Framework Weiteres Wissenswertes Übersicht Java Collection Framework Einleitung Ausgewählte Klassen Iteratoren Weiteres Wissenswertes RT (ICS @ UIBK) Programmiermethodik 455/613 Java Collection Framework Weiteres Wissenswertes Abstrakte Collection-Klassen • Unterstützen die Entwicklung neuer Collection-Klassen • Abstrakte Klassen implementieren schon großen Teil eines Interfaces und lassen bestimmte Teile offen • Neue Collection-Klasse kann auf abstrakte Klasse aufbauen (muss nicht alle Methoden eines Interfaces implementieren) • Vorgehensweise bei Implementierung einer neuen Collection-Klasse • Auswählen einer geeigneten abstrakten Klasse, von der geerbt wird • Implementierung aller abstrakten Methoden • Sollte Collection modifizierbar sein, dann müssen auch einige konkrete Methoden überschrieben werden (Beschreibung in API-Dokumentation der abstrakten Klasse) • Testen der neuen Klasse (inklusive Performance) RT (ICS @ UIBK) Programmiermethodik 456/613 Java Collection Framework Weiteres Wissenswertes Beispiele für abstrakte Klassen • Beispiele • AbstractCollection • AbstractSet • AbstractList (basierend auf Array) • AbstractSequentialList (basierend auf verketteter Liste) • AbstractQueue • AbstractMap • In API-Dokumentation jeder abstrakten Klasse wird beschrieben, wie man Klasse davon ableiten muss • Grundlegende Implementierung • Welche Methoden müssen implementiert werden • Welche Methoden müssen überschrieben werden, wenn man Modifikationen zulassen möchte RT (ICS @ UIBK) Programmiermethodik 457/613 Java Collection Framework Weiteres Wissenswertes Algorithmen im Collection-Framework • Collection-Framework bietet neben vordefinierten Containerklassen auch Algorithmen für Verarbeitung von Container-Klassen an • Algorithmen werden als statische Methoden (polymorphe Methoden) in Hilfsklasse Collections gesammelt • Algorithmen (Beispiele) • sort : Sortiert Elemente einer generischen Liste nach aufsteigender Größe • binarySearch: Sucht Element in sortierter Liste (Voraussetzung) und liefert Index zurück, wenn Element gefunden wurde (sonst: negative Zahl) • max: Liefert größtes Element einer Collection • shuffle : Mischt Elemente einer generischen Liste zufällig RT (ICS @ UIBK) Programmiermethodik 458/613 Java Collection Framework Weiteres Wissenswertes Vergleiche • Viele Methoden (z.B. sort , binarySearch) vergleichen Elemente der Größe nach • Benötigt Vergleichsoperation ⇒ Klassen müssen generisches Interface Comparable<T> implementieren (siehe Folie 377) RT (ICS @ UIBK) Programmiermethodik 459/613 Java Collection Framework Weiteres Wissenswertes Comparator • Oft sollen Objekte nach verschiedenen Kriterien verglichen werden • Daher sind viele Collection-Methoden mit zusätzlichem Parameter, einem Comparator, überladen • Erfüllt gleichen Zweck • Zum Vergleich wird aber übergebenes Comparator-Objekt benutzt • Comparator<T> ist generisches Interface mit einer Methode compare Methode akzeptiert zwei Objekte des Elementtyps und liefert ein int-Ergebnis für den Vergleich zweier Objekte RT (ICS @ UIBK) Programmiermethodik 460/613 Java Collection Framework Weiteres Wissenswertes Beispiel p u b l i c s t a t i c v o i d main ( f i n a l S t r i n g [ ] a r g s ) { L i s t <S t r i n g > s s = new A r r a y L i s t <S t r i n g > ( ) ; s s . add ( "Hans" ) ; s s . add ( "eva" ) ; s s . add ( " Gretel " ) ; System . o u t . p r i n t l n ( s s ) ; // Hans e v a G r e t e l Collections . sort ( ss ); System . o u t . p r i n t l n ( s s ) ; // G r e t e l Hans e v a Comparator<S t r i n g > i g n o r e C a s e C o m p a r a t o r ; i g n o r e C a s e C o m p a r a t o r = new Comparator<S t r i n g >() { p u b l i c i n t compare ( S t r i n g s1 , S t r i n g s 2 ) { r e t u r n ( s 1 . t o L o w e r C a s e ( ) . compareTo ( s2 . toLowerCase ( ) ) ) ; } }; C o l l e c t i o n s . s o r t ( ss , ignoreCaseComparator ) ; System . o u t . p r i n t l n ( s s ) ; // e v a G r e t e l Hans } RT (ICS @ UIBK) Programmiermethodik 461/613 Java Collection Framework Weiteres Wissenswertes Anonyme Klassen • können eingesetzt werden, um schnell ein Interface zu implementieren • kein Klassen Name erforderlich • keine eigene Java-Datei erforderlich • Syntax: . . . code w i t h i n some method . . . new I n t e r f a c e N a m e ( ) { public void m e t h o d O f I n t e r f a c e ( ) { ... } } . . . code w i t h i n some method • innerhalb der anonymen Klasse hat man Zugriff auf • finale Variablen der umgebenen Methode • Member-Variablen der umgegebenen Klasse (mittels ClassName.this.varName ) RT (ICS @ UIBK) Programmiermethodik 462/613 Java Collection Framework Weiteres Wissenswertes p u b l i c c l a s s R e v e r s e I t e r a b l e <T> implements I t e r a b l e <T> { private f i n a l T [ ] data ; p u b l i c R e v e r s e I t e r a b l e (T [ ] d a t a ) { t h i s . data = data ; } p u b l i c I t e r a t o r <T> i t e r a t o r ( ) { r e t u r n new I t e r a t o r <T>() { i n t pos = R e v e r s e I t e r a b l e . t h i s . data . l e n g t h ; p u b l i c boolean h a s N e x t ( ) { return t h i s . pos > 0 ; } public T next () { i f ( t h i s . hasNext ( ) ) { t h i s . pos −−; return R e v e r s e I t e r a b l e . t h i s . data [ t h i s . pos ] ; } e l s e throw new N o S u c h E l e m e n t E x c e p t i o n ( ) ; } p u b l i c v o i d remove ( ) { throw new U n s u p p o r t e d O p e r a t i o n E x c e p t i o n ( ) ; } }; } } RT (ICS @ UIBK) Programmiermethodik 463/613 Java Collection Framework Weiteres Wissenswertes Unveränderliche Collection-Klassen • Manchmal möchte man Container-Klassen zur Verfügung stellen, die unveränderlich sind • Klasse Collections bietet statische Methoden, mit denen unveränderliche Sichten auf vorhandene Container erzeugt werden können • Sichten auf Datenstruktur kopieren zugrunde liegende Datenstruktur nicht • Bieten eingeschränkte Darstellung (z.B. Sperren aller schreibenden Methoden) ⇒ Datenstruktur kann nicht verändert werden RT (ICS @ UIBK) Programmiermethodik 464/613 Java Collection Framework Weiteres Wissenswertes Beispiele • Methoden (Auswahl) p u b l i c s t a t i c <T> L i s t <T> u n m o d i f i a b l e L i s t ( L i s t <? extends T> l ) p u b l i c s t a t i c <K, V> Map<K, V> u n m o d i f i a b l e M a p (Map<? extends K, ? extends V> m) p u b l i c s t a t i c <T> Set<T> u n m o d i f i a b l e S e t ( Set <? extends T> s ) • Anwendung HashMap<S t r i n g , I n t e g e r > m = new HashMap < >(); ... Map<S t r i n g , I n t e g e r > rom ; rom = C o l l e c t i o n s . u n m o d i f i a b l e M a p (m) ; rom . p u t ( " TEST " , 1 ) ; // E x c e p t i o n m. p u t ( " TEST " , 1 ) ; // k e i n F e h l e r , g e f a e h r l i c h r e t u r n rom ; // n o r m a l e Anwendung RT (ICS @ UIBK) Programmiermethodik 465/613 Java Collection Framework Weiteres Wissenswertes Übersicht (wichtige Klassen) Typ ArrayList LinkedList HashSet LinkedHashSet TreeSet HashMap LinkedHashMap TreeMap RT (ICS @ UIBK) Ordnung bleibt null-Werte Duplikate 3 3 7 3 3 7 3 3 3 3 3 3 7 3 3 keys: 7, values: 3 3 3 7 7 7 keys: 7, values: 3 keys: 7, values: 3 keys: 7, values: 3 Programmiermethodik 466/613 Unit Tests Übersicht Unit Tests Testen Unit-Tests mit JUnit RT (ICS @ UIBK) Programmiermethodik 467/613 Unit Tests Testen Übersicht Unit Tests Testen Unit-Tests mit JUnit RT (ICS @ UIBK) Programmiermethodik 468/613 Unit Tests Testen Testen allgemein • Testen ist der Vorgang, ein Programm oder Teil davon mit der Absicht auszuführen, möglicherweise enthaltene Fehler zu finden • Testen dient zur Sicherstellung von Softwarequalität • Dazu werden spezifizierte Anforderungen mit gelieferten Ergebnissen verglichen RT (ICS @ UIBK) Programmiermethodik 469/613 Unit Tests Testen Abgrenzung zur Verifikation • Verifikation = formaler Korrektheitsbeweis • Es wird versucht, mit formalen Methoden den Nachweis zu führen, dass Programm nur richtige Ergebnisse produzieren kann • Liefert endgültige Aussage zur Korrektheit • Schon für kleine Programme kann Ansatz sehr aufwändig sein • Testen = systematisches Ausprobieren • Es wird bestimmte Anzahl von Tests konstruiert, mit denen das Programm probeweise ausgeführt wird • Mit Testen kann nur die Anwesenheit von Fehlern nachgewiesen werden, nicht aber deren Abwesenheit • Eigentlich benötigt man große Anzahl von Testfällen, um Programm ausführlich zu testen • Das verursacht aber meist sehr hohe Kosten • Endgültiger Korrektheitsbeweis ist damit auch nicht möglich RT (ICS @ UIBK) Programmiermethodik 470/613 Unit Tests Testen Testen • Um Anzahl der Tests möglichst klein zu halten, wählt man jene Tests aus, die Programm in kritische Situationen bringen • In diesen Situationen sind Fehler am ehesten zu erwarten • Zwei Vorgehensweisen beim Testen • Black-Box-Test • • • • Nur die Anforderungen des Programms werden berücksichtigt Schnittstelle gibt Testfälle vor Source-Code spielt keine Rolle, Programm wird als Black-Box betrachtet Änderungen am Quelltext (nicht Schnittstelle) erfordern keine neue Implementierung der Tests • White-Box • Test orientiert sich am Quelltext des Programms • Mit den Testfällen möchte man alle Codeabschnitte erfassen und die einzelnen Zweige, Schleifen etc. explizit austesten • Änderungen am Quelltext erfordern teilweise neue Tests bzw. alte Tests werden überflüssig RT (ICS @ UIBK) Programmiermethodik 471/613 Unit Tests Testen Tests (Überblick) einfach aufwändig Programmiermethodik selten RT (ICS @ UIBK) häufig • Kunde • Abnahmetest (Applikation) Handarbeit • Tester • Funktionstest (Teilsystem, Gesamtsystem) • Applikationstest (Gesamtsystem, Applikation) automatisierbar • Entwickler • Unit-Test (Methode, Klasse) • Komponententest (Klasse, Package) • Integrationstest (Teilsystem) 472/613 Unit Tests Unit-Tests mit JUnit Übersicht Unit Tests Testen Unit-Tests mit JUnit RT (ICS @ UIBK) Programmiermethodik 473/613 Unit Tests Unit-Tests mit JUnit Unit-Test • Beim Unit-Test wird kleine Einheit eines Programms betrachtet und auf mögliche Fehler untersucht • Einheit wird isoliert vom Rest des Gesamtsystems betrachtet • Man testet nur den speziellen Softwarebaustein • Testfälle werden direkt als Java-Programme erstellt (Entwickler können ihre Stärken ausnutzen) • Es gibt Programmiermethoden, bei denen dieses Testen elementarer Teil des Programmierens ist • Extreme Programming • Test-Driven Development RT (ICS @ UIBK) Programmiermethodik 474/613 Unit Tests Unit-Tests mit JUnit JUnit • JUnit bietet einheitliches Framework zur Organisation und systematischen Durchführung von Unit-Tests • Bibliothek ist nicht Teil des JDK sondern kann unter http://www.junit.org/ heruntergeladen werden • weiterführende Links • http://www.junit.org/ • http://junit.sourceforge.net/doc/faq/faq.htm RT (ICS @ UIBK) Programmiermethodik 475/613 Unit Tests Unit-Tests mit JUnit Verwendung • Entsprechendes jar-Archiv (junit-version.jar) muss in CLASSPATH eingebunden werden • JUnit wird für Unit-Tests verwendet, die die Korrektheit von isolierten Klassen prüfen • Entweder Test gelingt (grün) oder misslingt (rot) • Das Misslingen kann als Ursache einen Fehler (Error) oder ein falsches Ergebnis (Failure) haben, die beide durch Ausnahme signalisiert werden • Unterschied zwischen den Begriffen liegt darin, dass Failures erwartet werden, während Errors eher unerwartet auftreten RT (ICS @ UIBK) Programmiermethodik 476/613 Unit Tests Unit-Tests mit JUnit Vorgehen • Zuerst werden Ergebnisse in Form von Testfällen implementiert • Danach wird Code entwickelt • Nach Testfällen werden zunächst leere Methoden oder Methoden mit einer einzigen return-Anweisung definiert • Übersetzung funktioniert, Tests schlagen noch alle fehl • Danach werden Methodenrümpfe schrittweise vervollständigt, bis am Ende alle Tests fehlerfrei durchlaufen werden • Vorteile bei diesem Vorgehen • Tests werden zuerst erstellt • Ausgeglichene Sicht auf die geforderten Ergebnisse • Tests können nicht verdrängt werden • Tests geben notwendige Funktionalität vor RT (ICS @ UIBK) Programmiermethodik 477/613 Unit Tests Unit-Tests mit JUnit Vorgehen • In JUnit sind Tests Java-Objekte • Vor JUnit 4 musste man Testfälle von bestimmten JUnit-Klasse erben lassen • Ab Version 4 sollte man das aber nicht mehr machen • Diese Vorlesung: aktuelle stabile Version von JUnit (4.11) • Testmethoden müssen mit einer @Test-Annotation versehen werden • Daneben gibt es noch weitere Annotationen • Man kann mehrere Testklassen in Test-Suites zusammenfassen • Damit Testklasse mit älteren Tests zusammenarbeiten kann public s t a t i c j u n i t . framework . Test s u i t e ( ) { r e t u r n new J U n i t 4 T e s t A d a p t e r ( Example . c l a s s ) ; } RT (ICS @ UIBK) Programmiermethodik 478/613 Unit Tests Unit-Tests mit JUnit Testmethoden • Eine Testmethode pro Test • Signatur der Testmethoden ist vorgegeben, Methodenname ist beliebig: @Test public void someName() • Berechnet tatsächliches Ergebnis (have), vergleicht es mit korrektem Ergebnis (want) • Beide gleich ⇒ Test erfolgreich • Verschieden ⇒ Test gescheitert • Schematischer Aufbau einer Testmethode @Test public void t e s t ( ) { i n t want = . . . ; i n t hav e = . . . ; a s s e r t E q u a l s ( want , h a v e ) ; } RT (ICS @ UIBK) Programmiermethodik 479/613 Unit Tests Unit-Tests mit JUnit Vergleiche • JUnit bietet verschiedene Methoden zum Vergleich von den Werten want und have (Klasse Assert): • • • • • • assertFalse (boolean condition) assertTrue (boolean condition) assertEquals (long w, long h) assertEquals (double w, double h) assertEquals (double w, double h, double d) assertEquals (Object w, Object h) • Viele weitere, siehe API-Dokumentation • Alle Vergleichsmethoden sind überladen mit zusätzlichem ersten Parameter message, zum Beispiel: • assertFalse ( String message, boolean condition) • assertEquals (Object w, Object h) erfordert Definition von equals RT (ICS @ UIBK) Programmiermethodik 480/613 Unit Tests Unit-Tests mit JUnit Testklasse • Es gibt eine Testklasse für jede zu testende Klasse • Testklasse importiert benötigte JUnit-Klassen und Methoden • Testklasse definiert Testmethoden und Verwaltungsmethoden • Zweck der Methoden wird festgelegt mit einer Annotation • @Test: Testmethode (mehrfach) • @Before: Wird vor jedem einzelnen Test aufgerufen • @After: Wird nach jedem einzelnen Test aufgerufen • @BeforeClass: Wird einmal vor allen Tests aufgerufen • @AfterClass: Wird einmal nach allen Tests aufgerufe RT (ICS @ UIBK) Programmiermethodik 481/613 Unit Tests Unit-Tests mit JUnit Einfaches Beispiel • Zu testende Klasse GCD mit folgender Methode public static int gcd(int a, int b) • Testfall für gcd(1, 1) = 1: @Test public void t e s t 1 ( ) { i n t want = 1 ; i n t hav e = GCD . gcd ( 1 , 1 ) ; a s s e r t E q u a l s ( want , h a v e ) ; } RT (ICS @ UIBK) Programmiermethodik 482/613 Unit Tests Unit-Tests mit JUnit Komplexeres Beispiel • Wenn man z.B. auf gemeinsames Objekt mehrere verschiedene Tests ausführen möchte, dann kann man mit sogenannter Test-Fixture Code-Duplizierung vermeiden • Siehe Eclipse-Beispiel StackTest. java RT (ICS @ UIBK) Programmiermethodik 483/613 Unit Tests Unit-Tests mit JUnit Erwarteter Fehler • Reaktion auf unzulässige Eingaben (z.B. Exception) • Vorgabe der erwarteten Exception • Test scheitert, wenn Exception nicht geworfen wird • Testfall für gcd(1, 0): @Test ( e x p e c t e d = A r i t h m e t i c E x c e p t i o n . c l a s s ) public void t e s t 1 0 ( ) { i n t dummy = 0 ; i n t hav e = GCD . gcd ( 1 , 0 ) ; a s s e r t E q u a l s (dummy , h a v e ) ; } • Beispiel: popEmptyTest(); RT (ICS @ UIBK) Programmiermethodik 484/613 Unit Tests Unit-Tests mit JUnit Testabwicklung • Im Java-Programm selbst • org . junit .runner.JUnitCore. runClasses (TestClass1 . class , ...); oder • org . junit .runner.JUnitCore.main("TestClass1"); • Unterschied: runClasses liefert Ergebnis, das weiterverarbeitet werden kann • Start der Testklasse auf der Konsole • Testklasse(n) und JUnit im Classpath • java org.junit.runner.JUnitCore TestClass1 ... • java -cp "../hamcrest-core-1.3.jar:../junit-4.11.jar:." org.junit.runner.JUnitCore junit.StackTest • Testabwicklung in Eclipse • Unter Run – Run As – JUnit Test kann Test gestartet werden • Neben Package-Explorer gibt es dann zusätzliches Subfenster, in dem Testergebnisse angezeigt werden RT (ICS @ UIBK) Programmiermethodik 485/613 Entwurfsmuster Übersicht Entwurfsmuster Einführung Überblick Erzeugungsmuster Strukturmuster Verhaltensmuster RT (ICS @ UIBK) Programmiermethodik 486/613 Entwurfsmuster Einführung Übersicht Entwurfsmuster Einführung Überblick Erzeugungsmuster Strukturmuster Verhaltensmuster RT (ICS @ UIBK) Programmiermethodik 487/613 Entwurfsmuster Einführung Wiederholung (Objektorientierte Konzepte) • Bisher besprochen • Klassen und Interfaces • Vererbung • Überladen • Überschreiben • Polymorphismus • Dynamisches Binden • Wie verwendet man diese Konzepte? • Was bildet man auf Klassen ab? • Wie sehen Beziehungen zwischen Klassen aus? • Vererbung? • Komposition? • Wo werden bestimmte Methoden definiert? RT (ICS @ UIBK) Programmiermethodik 488/613 Entwurfsmuster Einführung Wiederholung (Wiederverwendung von Software) • Vererbung (Implementierung) • Subklasse erbt Implementierung der Superklasse • Teile der Superklasse sind in Subklasse sichtbar (White Box Reuse) • Komposition • Objekte benutzen andere Objekte • Internas sind aufrufendem Objekt nicht bekannt • Nur Schnittstelle ist bekannt (Black Box Reuse) RT (ICS @ UIBK) Programmiermethodik 489/613 Entwurfsmuster Einführung Vererbung • Vorteile • Einfache Methode für Wiederverwendung • Polymorphismus • Sprachunterstützung • Nachteile • Statischer Mechanismus, da Implementierung der Superklasse nicht dynamisch geändert werden kann • Veränderungen an Superklasse können Subklassen beeinflussen (Problem der instabilen Basisklassen) • Wiederverwendung der Subklasse eingeschränkt (Abhängigkeit von der Superklasse) RT (ICS @ UIBK) Programmiermethodik 490/613 Entwurfsmuster Einführung Komposition • Vorteile • Dynamischer Mechanismus, da Referenz auf ein anderes Objekt zur Laufzeit bestimmt werden kann • Kapselung wird nicht verletzt (nur Interface berücksichtigen) • Nachteile • Code muss oft mehrmals implementiert werden • Mehr Klassen müssen implementiert werden • Systemverhalten ist nicht mehr in einer Klasse definiert (hängt von Klassenbeziehungen ab) • Komposition sollte in einigen Fällen der Vererbung vorgezogen werden (z.B. bei Abhängigkeit von fremden Klassen) RT (ICS @ UIBK) Programmiermethodik 491/613 Entwurfsmuster Einführung Einleitendes Beispiel Shape • +display() ⇒ Rectangle Triangle Circle +display() +display() +display() • Wie modelliert man das? RT (ICS @ UIBK) Programmiermethodik 492/613 Entwurfsmuster Einführung Einleitendes Beispiel • Lösung? • Neue Implementierung der Shape-Klasse? • Andere (externe) Klasse? • Welche Methoden? • Wie werden Figuren zusammengesetzt? • Viele unterschiedliche Lösungen möglich • Problem dieser Komposition kann auch in anderen Bereichen auftauchen • Z.B. Dateisystem • Ordner beinhalten Dateien oder weitere Ordner, die wiederum Dateien und Ordner enthalten, die . . . RT (ICS @ UIBK) Programmiermethodik 493/613 Entwurfsmuster Einführung Mögliche Lösung • 2 Arten (Elemente) • Atomare Komponenten (Blätter in Hierarchie) • Container (beinhalten weitere Elemente) • Container sollte atomare Elemente und Container aufnehmen können und diese auch gleich behandeln • Beide Elemente sind Komponenten (gleiche Klasse) • Basisstruktur Component Atomic Component RT (ICS @ UIBK) * Intermediate Container Programmiermethodik 494/613 Entwurfsmuster Einführung Funktionalität • Komponente kann andere Komponenten beinhalten • Methode add(Component) • Jede Komponente sollte zumindest eine Operation ausführen • Methode operation () • Operation auf Container sollte auf allen Teilkomponenten ausgeführt werden • Methode operation () muss entsprechend überschrieben / implementiert werden RT (ICS @ UIBK) Programmiermethodik 495/613 Entwurfsmuster Einführung Verbessertes Design • Neues Design mit minimaler Funktionalität Component Composite Client «use» * +operation() +add(c : Component) Atomic Component +operation() Intermediate Container +operation() +add(c : Component) operation(): for each g in children: g.operation() RT (ICS @ UIBK) Programmiermethodik 496/613 Entwurfsmuster Einführung Anwendung auf ursprüngliches Beispiel Shape «use» Screen * +display() +add(c : Shape) Circle Triangle Rectangle +display() +display() +display() ComposedShape +display() +add(c : Shape) display(): for each g in children: g.display() RT (ICS @ UIBK) Programmiermethodik 497/613 Entwurfsmuster Einführung Generalisierung • Gleiche Lösung kann in verschiedenen Situationen verwendet werden • Rollen wurden eindeutig identifiziert • Man muss nicht nochmals über Design nachdenken • Wiederverwendung der Architektur ⇒ Entwurfsmuster (Design Pattern) • Konkretes Beispiel wird als Kompositum (Composite Pattern) bezeichnet RT (ICS @ UIBK) Programmiermethodik 498/613 Entwurfsmuster Überblick Übersicht Entwurfsmuster Einführung Überblick Erzeugungsmuster Strukturmuster Verhaltensmuster RT (ICS @ UIBK) Programmiermethodik 499/613 Entwurfsmuster Überblick Historisches • Entwurfsmuster sind nicht neu • Beispiel Architektur • Architektur von Häusern • Stadtplanung • In der Softwareentwicklung • Entwurfsmuster (Design Pattern) beschreibt bewährte Schablone für Entwurfsproblem • Ideen aus der Architektur übernommen • Softwareerstellung basiert auf bekannten (bewährten) Mustern • “Das Rad nicht immer neu erfinden” • Etablierte Lösungen aus der Vergangenheit verwenden bzw. anpassen • Hauptreferenz: Erich Gamma, Richard Helm, Ralph Johnson und John Vlissides Design Patterns: Elements of Reusable Object-Oriented Software Addison-Wesley RT (ICS @ UIBK) Programmiermethodik 500/613 Entwurfsmuster Überblick Entwurfsmuster • Entwurfsmuster beschreibt Problem, welches immer wieder auftritt • Es beschreibt allgemeinen Kern der Lösung • Muster kann dann zum Lösen eines neuen Problems verwendet werden • Ein gutes Muster sollte . . . • Ein oder mehrere Probleme lösen • Ein erprobtes Konzept bieten • Auf realen Designs basieren • Über das rein Offensichtliche hinausgehen • Den Benutzer in den Entwurfsprozess einbinden • Beziehungen aufzeigen, die tiefergehende Strukturen und Mechanismen eines Systems umfassen RT (ICS @ UIBK) Programmiermethodik 501/613 Entwurfsmuster Überblick Entwurfsmuster: Elemente • Name • Beschreibt kurz und bündig, worum es geht • Erweitert das Design-Vokabular • Problem • Beschreibt die Anwendung • Es wird das Problem und entsprechender Kontext beschrieben • Lösung • Beschreibt die einzelnen Elemente • Beteiligte Klassen mit Verantwortungen • Beziehungen • Verantwortung und Zusammenspiel der Klassen • Kann als allgemeine Schablone (Template) aufgefasst werden • Abstrakte Beschreibung eines Design-Problems und seiner Lösung • Auswirkungen • Wie wirkt sich der Einsatz aus? • Vor- bzw. Nachteile? RT (ICS @ UIBK) Programmiermethodik 502/613 Entwurfsmuster Überblick Klassifikation • Erzeugungsmuster • Wie kann man Erzeugung von Objekten unterstützen? • Erzeugungsmuster entkoppeln die Konstruktion eines Objekts von seiner Repräsentation • Strukturmuster • Wie kann man Klassen/Interfaces verbinden, um Objekte zu erzeugen, die neue Funktionalität realisieren? • Verhaltensmuster • Wie kann man Interaktion zwischen Objekten und komplexen Algorithmen/Kontrollflüssen beschreiben? • Wie gruppiert man Objekte, um Aufgaben zu lösen, die nicht von einem Objekt alleine gelöst werden können? RT (ICS @ UIBK) Programmiermethodik 503/613 Entwurfsmuster Überblick Klassifikation Bereich Erzeugungsmuster Bereich Strukturmuster Klasse Fabrikmethode Adapter (klassenbasiert) Objekt Abstrakte Erbauer Prototyp Singleton Adapter (objektbasiert) Brücke Dekorierer Fassade Fliegengewicht Kompositum Stellvertreter RT (ICS @ UIBK) Fabrik Programmiermethodik Verhaltensmuster Interpreter Schablonenmethode Befehl Beobachter Besucher Iterator Memento Strategie Vermittler Zustand Zuständigkeitskette 504/613 Entwurfsmuster Überblick Klassifikation Bereich Bereich Erzeugungsmuster Strukturmuster Verhaltensmuster Klasse Factory Method Adapter (class) Objekt Abstract Factory Builder Prototype Singleton Adapter (object) Bridge Decorator Facade Flyweight Composite Proxy RT (ICS @ UIBK) Programmiermethodik Interpreter Template Methode Command Observer Visitor Iterator Memento Strategy Mediator State Chain of Responsibility 505/613 Entwurfsmuster Überblick Weitere Muster • Bisher beschriebene Muster sind grundlegende Muster • Es wurden mittlerweile viele weitere Muster vorgeschlagen, die aber nicht zu den Entwurfsmustern gezählt werden • Analysemuster • Typische Fälle der Anforderungsanalyse • Architekturmuster • Beschreiben typische Softwarearchitekturen • Idiom (Softwaretechnik) • Muster, die unterhalb der Ebene des Entwurfs bei der Programmierung auftreten • Kommunikationsmuster • Beziehen sich auf Kommunikationswege zwischen Personen einer Organisation • Organisationsmuster • Beschreiben Elemente der Strukturen von Organisationen • Antimuster • Beschreiben, wie man es nicht machen sollte • Beispiele: “Gott-Objekt” (Objekt, das alles weiß und kann), “Spaghetti-Code” (Code ohne Struktur) , Programmierung mittels Copy & Paste RT (ICS @ UIBK) Programmiermethodik 506/613 Entwurfsmuster Erzeugungsmuster Übersicht Entwurfsmuster Einführung Überblick Erzeugungsmuster Strukturmuster Verhaltensmuster RT (ICS @ UIBK) Programmiermethodik 507/613 Entwurfsmuster Erzeugungsmuster Singleton • Name • Singleton • Zweck • Es sollte nur eine Instanz einer Klasse angelegt werden • Die Erzeugung sollte nur an einer Stelle geschehen • Motivation • Bestimmte Klasse sollte nur einmal vorhanden sein • Z.B. nur ein Drucker-Spooler, nur ein Window-Manager etc. • Globale Variable würde OO-Prinzipien verletzen • Klasse sollte selbst für Verwaltung Ihrer Instanz verantwortlich sein • Anwendbarkeit • Es sollte nur genau ein Exemplar dieser Klasse vorhanden sein und diese sollte nur über einen Zugriffspunkt erreichbar sein • Es muss möglich sein, eine Erweiterung des Singletons zu realisieren und die Klienten müssen sich nicht darum kümmern RT (ICS @ UIBK) Programmiermethodik 508/613 Entwurfsmuster Erzeugungsmuster Singleton • Struktur Singleton –instance: Singleton –singletonData return instance; –Singleton() +getInstance() +operation() +getData() • Beteiligte Akteure • Singleton • Definiert Operation für Zugriff auf einzige Instanz • Ist für die Erzeugung der einzigen Instanz verantwortlich • Zusammenspiel • Klienten greifen nur über entsprechende Methode auf Instanz zu RT (ICS @ UIBK) Programmiermethodik 509/613 Entwurfsmuster Erzeugungsmuster Singleton • Vorteile • Kontrollierter Zugriff auf einzige Instanz • Reduzierter Namensraum (im Vergleich zu statischen Konstanten) • Erlaubt auch variable Anzahl von Instanzen • Nur Methode getInstance () ändern • Flexibler als Klassenmethoden • Erlaubt auch Vererbung • Nachteile • Exzessive Verwendung von Singletons simuliert globale Variablen • Testbarkeit von Singletons ist schlecht • Synchronisation muss bei nebenläufigen Programmen berücksichtigt werden • In einigen objektorientierten Programmiersprachen gibt es keine Möglichkeit, Klassenmethoden zu schreiben RT (ICS @ UIBK) Programmiermethodik 510/613 Entwurfsmuster Erzeugungsmuster Singleton • Implementierung • Sicherstellen, dass nur eine Instanz existiert • Ableiten von Singleton-Klasse • Implementierungsabhängig • Praxiseinsatz • Weit verbreitet • Typischerweise bei GUIs • Querverweise • Viele andere Muster können als Singleton implementiert werden • Siehe zum Beispiel Abstrakte Fabrik RT (ICS @ UIBK) Programmiermethodik 511/613 Entwurfsmuster Erzeugungsmuster Singleton: Beispielcode public class C l a s s i c S i n g l e t o n { private static ClassicSingleton instance = null ; p r i v a t e C l a s s i c S i n g l e t o n ( ) {} public static C l a s s i c S i n g l e t o n getInstance () { i f ( i n s t a n c e == n u l l ) { // n o t t h r e a d s a f e i n s t a n c e = new C l a s s i c S i n g l e t o n ( ) ; } return i n s t a n c e ; } } public class Singleton { // t h r e a d s a f e i n i t d u r i n g c l a s s l o a d i n g p r i v a t e s t a t i c S i n g l e t o n i n s t a n c e = new S i n g l e t o n ( ) ; p r i v a t e S i n g l e t o n ( ) {} public static Singleton getInstance () { return i n s t a n c e ; } } RT (ICS @ UIBK) Programmiermethodik 512/613 Entwurfsmuster Erzeugungsmuster Abstrakte Fabrik • Name • Abstrakte Fabrik (engl.: Abstract Factory, Kit) • Zweck • Schnittstelle für Erzeugen von Objektfamilien oder verwandten Objekten anbieten • Konkrete Klassen sind nicht bekannt • Motivation • Beispiel GUIs • Unterschiedliche Look-and-feel-Standards implementieren • Für Portierbarkeit sollte Applikation nicht die einzelnen GUI-Komponenten für jeden Standard extra kodieren • Benutzer sollte unabhängig von Standard arbeiten können • Lösung (siehe Beispiel) RT (ICS @ UIBK) Programmiermethodik 513/613 Entwurfsmuster Erzeugungsmuster Abstrakte Fabrik • Anwendbarkeit • Wenn System unabhängig von Art der Erzeugung seiner Produkte arbeiten soll • Wenn System mit einer oder mehreren Produktfamilien konfiguriert werden soll • Wenn Gruppe von Produkten erzeugt und gemeinsam genutzt werden soll • Wenn in Klassenbibliothek die Schnittstellen von Produkten ohne deren Implementierung bereitgestellt werden sollen RT (ICS @ UIBK) Programmiermethodik 514/613 Entwurfsmuster Erzeugungsmuster Abstrakte Fabrik: Struktur AbstractFactory ProductClient +createProductA() +createProductB() ConcreteFactory1 ConcreteFactory2 +createProductA() +createProductB() +createProductA() +createProductB() AbstractProductA ProductA1 ProductA2 AbstractProductB ProductB1 RT (ICS @ UIBK) ProductB2 Programmiermethodik 515/613 Entwurfsmuster Erzeugungsmuster Abstrakte Fabrik • Beteiligte Akteure • AbstractFactory • Schnittstelle für Operationen, die zur Erzeugung abstrakter Produkte dienen • ConcreteFactory • Implementiert Operationen zur Erzeugung konkreter Produktobjekte • AbstractProduct • Definiert eine Schnittstelle für Produkttyp • ConcreteProduct • Konkrete Implementierung eine Produkts • Client • Benutzt nur die Schnittstellen AbstractFactory und AbstractProduct • Zusammenspiel • Eine Instanz einer ConcreteFactory zur Laufzeit • Erzeugt Produktobjekte mit bestimmter Implementierung RT (ICS @ UIBK) Programmiermethodik 516/613 Entwurfsmuster Erzeugungsmuster Abstrakte Fabrik • Konsequenzen • Vorteile • Isoliert konkrete Klassen • Austausch von Produktfamilien sehr einfach • Fördert Konsistenz zwischen Produkten einer Produktfamilie • Nachteile • Erweiterung mit neuen Produktfamilien ist umständlich • Schnittstelle der abstrakten Fabrik legt Produkte fest • Implementierung • Fabriken werden oft als Singletons implementiert • Konkrete Fabrik muss alle Methoden überschreiben • Erweiterbarkeit • Abstrakte Fabrik bietet nur eine make-Methode mit Parameter an • Parameter gibt die Art des Produkts an • Querverweise • Singleton (siehe Implementierung) RT (ICS @ UIBK) Programmiermethodik 517/613 Entwurfsmuster Erzeugungsmuster Struktur: Konkretes Beispiel WidgetFactory WidgetClient +createScrollbar() +createWindow() MotifWidgetFactory MetalWidgetFactory +createScrollbar() +createWindow() +createScrollbar() +createWindow() AbstractScrollbar MotifScrollbar MetalScrollbar AbstractWindow MotifWindow RT (ICS @ UIBK) MetalWindow Programmiermethodik 518/613 Entwurfsmuster Erzeugungsmuster Beispiel public abstract c l a s s GUIFactory { private f i n a l s t a t i c GUIFactory f a c t o r y ; static { i n t s y s ; // . . . d e t e r m i n e s s y s t e m f a c t o r y = ( s y s == 0 ? new W i n F a c t o r y ( ) : new OSXFactory ( ) ) ; } public s t a t i c GUIFactory getFactory () { r e t u r n f a c t o r y ; // s i n g l e t o n w i t h i n h e r i t a n c e } p u b l i c a b s t r a c t Button c r e a t e B u t t o n ( ) ; } p u b l i c c l a s s W i n F a c t o r y extends G U I F a c t o r y { p u b l i c Button c r e a t e B u t t o n ( ) { r e t u r n new WinButton ( ) ; }} p u b l i c c l a s s OSXFactory extends G U I F a c t o r y { p u b l i c Button c r e a t e B u t t o n ( ) { r e t u r n new OSXButton ( ) ; RT (ICS @ UIBK) Programmiermethodik 519/613 Entwurfsmuster Erzeugungsmuster Beispiel p u b l i c i n t e r f a c e Button { public void p a i n t ( ) ; } p u b l i c c l a s s WinButton implements Button { public void p a i n t ( ) { System . o u t . p r i n t l n ( " WinButton : " ) ; } } p u b l i c c l a s s OSXButton implements Button { public void p a i n t ( ) { System . o u t . p r i n t l n ( " OSXButton : " ) ; } } public class Application { p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { GUIFactory f a c t o r y = GUIFactory . getFactory ( ) ; Button b u t t o n = f a c t o r y . c r e a t e B u t t o n ( ) ; button . paint ( ) ; ... RT (ICS @ UIBK) Programmiermethodik 520/613 Entwurfsmuster Erzeugungsmuster Weitere Erzeugungsmuster • Fabrikmethode • Definiert Klassenschnittstelle mit Operationen zum Erzeugen eines Objektes, aber lässt Unterklassen entscheiden, von welcher Klasse das zu erzeugende Objekt ist • Erbauer • Trennt Konstruktion eines komplexen Objekts von seiner Repräsentation so, dass derselbe Konstruktionsprozess unterschiedliche Repräsentationen erzeugen kann • Prototyp • Bestimmt Arten zu erzeugender Objekte durch Verwendung eines prototypischen Exemplars, und erzeugt neue Objekte durch Kopieren dieses Prototypen RT (ICS @ UIBK) Programmiermethodik 521/613 Entwurfsmuster Strukturmuster Übersicht Entwurfsmuster Einführung Überblick Erzeugungsmuster Strukturmuster Verhaltensmuster RT (ICS @ UIBK) Programmiermethodik 522/613 Entwurfsmuster Strukturmuster Adapter • Name • Klassenbasierter Adapter, Objektbasierter Adapter • engl.: Adapter(class), Adapter(object) (synonym: Wrapper) • Zweck • Schnittstelle einer Klasse in andere von Klienten erwartete Schnittstelle konvertieren • Motivation • Oft möchte man Bibliothek verwenden, die aber keine kompatible Schnittstelle hat (die vom Benutzer erwartet wird) • Meist kann man Bibliothek nicht ändern • Man hat nicht den Quellcode • Man sollte nicht für jede neue Applikation die Schnittstelle einer Bibliothek ändern RT (ICS @ UIBK) Programmiermethodik 523/613 Entwurfsmuster Strukturmuster Adapter • Lösung • Es wird Klasse benutzt, die die Schnittstelle adaptiert • 2 Arten • Klassenbasierter Adapter basierend auf (Mehrfach)-Vererbung (Adapter implementiert Schnittstelle, erbt von Bibliotheksklasse) • Objektbasierter Adapter basierend auf Komposition (Adapter implementiert Schnittstelle, nutzt Bibliotheksklasse) • Anwendbarkeit • Wenn man Klasse benutzen möchte, deren Schnittstelle nicht der erwarteten Schnittstelle entspricht • Man möchte wiederverwendbare Klasse erzeugen, die mit nicht verwandten oder unvorhergesehenen Klassen zusammenarbeiten kann RT (ICS @ UIBK) Programmiermethodik 524/613 Entwurfsmuster Strukturmuster Adapter: Struktur (Klassenbasiert) AdapterClient «interface» Target +request() Adaptee +specificRequest() Adapter +request() ... specificRequest() ... RT (ICS @ UIBK) Programmiermethodik 525/613 Entwurfsmuster Strukturmuster Adapter: Struktur (Objektbasiert) Target Adaptee +request() +specificRequest() AdapterClient -adaptee Adapter +request() ... adaptee.specificRequest() ... RT (ICS @ UIBK) Programmiermethodik 526/613 Entwurfsmuster Strukturmuster Adapter • Beteiligte Akteure • Target • Definiert spezifische Schnittstelle, die Client benutzt • Client • Arbeitet mit Objekten zusammen, die die Target-Schnittstelle implementieren • Adaptee • Definiert existierende Schnittstelle, die adaptiert werden muss • Adapter • Adaptiert Schnittstelle von Adaptee auf erwartete Target-Schnittstelle • Zusammenspiel • Klienten können Target-Schnittstelle benutzen • Adapter ruft Operationen im Adaptee auf, um Aufrufe weiterzuleiten RT (ICS @ UIBK) Programmiermethodik 527/613 Entwurfsmuster Strukturmuster Adapter: Konsequenzen • Klassenbasierter Adapter • Kann nicht angewandt werden, wenn man Klasse und ihre Subklassen adaptieren möchte • Erlaubt dem Adapter das Überschreiben • Objektbasierter Adapter • Einzelner Adapter kann mit mehreren zu adaptierbaren Klassen (Klasse und Subklassen davon) zusammenarbeiten • Überschreiben von Verhalten wird schwieriger • Wie umfangreich fällt die Adaptierung aus? • Einfache Schnittstellenkonvertierung • Andere Namen für Operationen • Ändern der Anzahl oder Anordnung der Parameter • Änderung der Operationen • Spezielle Adapter (z.B. n-Weg Adapter) • Eine Adapterklasse kann mehrere Interfaces implementieren • So wird Klasse für 2 oder mehrere Klienten benutzbar RT (ICS @ UIBK) Programmiermethodik 528/613 Entwurfsmuster Strukturmuster Adapter • Implementierung • Abhängig von der Sprache (Mehrfachvererbung beim klassenbasierten Adapter oder Implementierung von Interfaces) • Implementierung von speziellen Adaptern • Unterschiedliche Ansätze (siehe Gamma-Buch) • Querverweise • Ähnlich zum Stellvertreter-Muster (siehe später) RT (ICS @ UIBK) Programmiermethodik 529/613 Entwurfsmuster Strukturmuster Kompositum • Name • Kompositum (engl.: Composite) • Zweck • Erstellt Baumstruktur von Objekten, um Teile-Ganzes-Hierarchie zu repräsentieren • Erlaubt Klienten, individuelle Objekte und zusammengesetzte Objekte einheitlich zu benutzen • Motivation • GUI-Applikationen • Verschiedene Komponenten, die wiederum in größere Komponenten gruppiert werden können. • Es wird rekursive Komposition benötigt, damit Klient keine Unterscheidung machen muss • Anwendbarkeit • Wenn man Teile-Ganzes-Beziehungen repräsentieren möchte • Klienten sollten Objekte (individuell, zusammengesetzt) einheitlich behandeln können RT (ICS @ UIBK) Programmiermethodik 530/613 Entwurfsmuster Strukturmuster Kompositum: Struktur Component +operation() +add(c : Component) +remove(c : Component) +getChild(ch : int) «use» Composite Client * -children Composite Leaf +operation() +operation() +add(c : Component) +remove(c : Component) +getChild(ch : int) for each g in children: g.operation() RT (ICS @ UIBK) Programmiermethodik 531/613 Entwurfsmuster Strukturmuster Kompositum • Beteiligte Akteure • Component • Definiert Schnittstelle für Objekte • Liefert Default-Implementierungen für Operationen, die allen Klassen gemeinsam sind (falls möglich) • Definiert Schnittstelle für Zugriff (und das Management) von Kindkomponenten • Optional: Definiert Schnittstelle für den Zugriff auf Vaterknoten in Kompositionsstruktur • Leaf • Repräsentiert Blatt, d.h. konkrete Klasse • Definiert Verhalten für primitive Komponenten • Composite • Definiert Verhalten für zusammengesetzte Komponenten • Speichert Kindkomponenten • Implementiert Operationen zur Verwaltung der Kindkomponenten • Client • Manipuliert Objekte in Komposition mit Hilfe der Component-Schnittstelle RT (ICS @ UIBK) Programmiermethodik 532/613 Entwurfsmuster Strukturmuster Kompositum • Zusammenspiel • Klienten benutzen Component-Schnittstelle, um mit Objekten in Komposition zu interagieren • Handelt es sich um Blatt, dann wird Operation direkt ausgeführt • Handelt es sich um zusammengesetzte Komponente, dann wird Aufruf an die Kindkomponenten weitergeleitet • Konsequenzen • Definiert Klassenhierarchien (rekursiv) • Einfacher Klient • Klient muss sich nicht um Art der Komponente kümmern • Erleichtert Hinzufügen von Komponenten • Neue Komponenten funktionieren automatisch in bestehenden Hierarchien und mit bestehendem Code • Klienten müssen nicht verändert werden. • Manchmal zu generell • Einschränkungen (Anzahl der Komponenten) möglich, aber umständlich • Einschränkungen auf Klassen umständlich (Typsystem hilft hier nicht) RT (ICS @ UIBK) Programmiermethodik 533/613 Entwurfsmuster Strukturmuster Kompositum: Implementierung • Explizite Referenzen auf Vaterknoten berücksichtigen • Maximierung der Komponenten-Schnittstelle • Implementierung der Management-Operationen (add()-Methode) • Unterstützung von Transparenz • Methode wird in Superklasse implementiert • Hat Implementierung mit Fehlerbehandlung • Im Blatt nicht sinnvoll • Container muss Methode sinnvoll überschreiben • Unterstützung von Sicherheit • Methode wird im Container implementiert • Klient muss aber nun testen, ob er Blatt oder Container benutzt • Verwaltung der Komponenten • Datenstruktur hängt von Applikation ab • Ordnung der Kindkomponenten (z.B. für Überlappungen in Grafiken) • Caching (von Durchläufen) • Löschen von Objekten (in Sprachen ohne Garbage-Collection) RT (ICS @ UIBK) Programmiermethodik 534/613 Entwurfsmuster Strukturmuster Kompositum • Beispielcode • Siehe CompositeClient.java • Querverweise • Beziehung bestehen zu einigen Entwurfsmustern • Iterator kann zum Traversieren benutzt werden RT (ICS @ UIBK) Programmiermethodik 535/613 Entwurfsmuster Strukturmuster Stellvertreter • Name • Stellvertreter (engl.: Proxy, Synonym: Surrogate) • Zweck • Bereitstellen eines Stellvertreters (Platzhalters) für Objekt, durch den Zugriff auf Objekt kontrolliert wird • Motivation • Zugriff auf Objekt soll nicht über direkte Referenz erfolgen • Beispiele • Z.B. Erzeugung des realen Objekts benötigt sehr viele Ressourcen und wird nur dann durchgeführt, wenn Objekt auch wirklich benötigt wird (ansonsten wird mit dem Platzhalter gearbeitet) • Zugriff erfordert Authentifizierung • Lösung • Gemeinsame Schnittstelle für reales Objekt und Stellvertreter • Stellvertreter hat Referenz auf reales Objekt • Benutzer verwendet Stellvertreter, der möglicherweise reales Objekt verwendet RT (ICS @ UIBK) Programmiermethodik 536/613 Entwurfsmuster Strukturmuster Stellvertreter: Anwendbarkeit • Immer wenn man eine “intelligente” Referenz auf Objekt benötigt • Remote Proxy • Entfernter Zugriff (Objekt in anderem Adressraum, über Netzwerk) • Virtual Proxy • Erzeugung speicherintensiver Objekte (reales Objekt wird erst beim ersten Zugriff erzeugt) • Protection Proxy • Zugriffsüberprüfung, differenzierter Zugriff für unterschiedliche Benutzer • Cache Proxy • Zwischenspeicherung von Resultaten für schnelleren Zugriff • Smart Reference • Zählen der Zugriffe • Persistenzoperationen • Locking RT (ICS @ UIBK) Programmiermethodik 537/613 Entwurfsmuster Strukturmuster Stellvertreter: Struktur «interface» Subject Proxy Client +request() RealSubject +request() Proxy -subject +request() ... subject.request() ... RT (ICS @ UIBK) Programmiermethodik 538/613 Entwurfsmuster Strukturmuster Stellvertreter • Beteiligte Akteure • Proxy • • • • • Verwaltet Referenz auf reales Subjekt Hat gleiche Schnittstelle wie Subjekt Kontrolliert Zugriff auf Subjekt Kann auch für Erzeugen und Löschen des Subjekts verantwortlich sein Weitere Verantwortung hängt von Art des Proxys ab • Subject • Definiert gemeinsame Schnittstelle für reales Subjekt und Proxy, damit Proxy als Stellvertreter benutzt werden kann • RealSubject • Definiert reales Subjekt, das der Proxy repräsentiert • Zusammenspiel • Proxy leitet Aufrufe an Subjekt weiter (abhängig vom Kontext und Art des Proxys) RT (ICS @ UIBK) Programmiermethodik 539/613 Entwurfsmuster Strukturmuster Stellvertreter • Konsequenzen • Zusätzliche Indirektion • Abhängig von Art des Proxys kann das unterschiedliche Konsequenzen haben: • Remote Proxy kann Umstand verbergen, dass sich angesprochenes Subjekt in einem anderen Adressraum befindet • Virtual Proxy kann Optimierungen vornehmen (z.B. copy-on-write) • Protection Proxy kann Zugriffsrechte eines Aufrufers überprüfen • Implementierung • Proxy muss nicht immer Typ des Subjekts kennen (nur Interface) • Vorteil: Proxy kann für mehrere konkrete Klassen verwendet werden • Nachteil: kein create-on-demand • Querverweise • Ähnlichkeit zu Adapter • Proxy hat aber gleiche Schnittstelle • Proxy kann Zugriffe unterbinden • Dekorierer • Dekorierer gibt aber Funktionalität dazu RT (ICS @ UIBK) Programmiermethodik 540/613 Entwurfsmuster Strukturmuster Weitere Strukturmuster • Fassade • Bietet einheitliche Schnittstelle zu Menge von Schnittstellen eines Subsystems • Brücke • Entkoppelt Abstraktion von Implementierung, so dass beide unabhängig voneinander variiert werden können • Dekorierer • Erweitert Objekt dynamisch um Zuständigkeiten • Fliegengewicht • Nutzt Objekte kleinster Granularität gemeinsam, um große Mengen von ihnen effizient verwenden zu können RT (ICS @ UIBK) Programmiermethodik 541/613 Entwurfsmuster Verhaltensmuster Übersicht Entwurfsmuster Einführung Überblick Erzeugungsmuster Strukturmuster Verhaltensmuster RT (ICS @ UIBK) Programmiermethodik 542/613 Entwurfsmuster Verhaltensmuster Iterator • Name • Iterator (Synonym: Cursor) • Zweck • Ermöglicht sequentiellen Zugriff auf Sammlung (komplexes Objekt), ohne die darunter liegende Struktur offen zu legen • Motivation • Sammlung von Elementen sollte Benutzer Möglichkeit für Traversierung aller Elemente anbieten • Benutzer sollte sich nicht um interne Struktur kümmern müssen • Traversieren sollte auf unterschiedliche Art und Weise stattfinden können (ohne Schnittstelle mit vielen Operationen) • Lösung: Spezielles Objekt für Zugriff und Traversierung (Iterator) • Schnittstelle; verwaltet aktuelle Traversierung (aktuelles Element) • Sammlung selbst ist für Erzeugung des Iterators verantwortlich RT (ICS @ UIBK) Programmiermethodik 543/613 Entwurfsmuster Verhaltensmuster Iterator • Anwendbarkeit • Wenn man auf komplexes Objekt ohne Kenntnis der internen Struktur zugreifen möchte • Wenn man unterschiedliche Traversierungsarten unterstützen möchte • Wenn man einheitliche Schnittstelle für Traversieren verschiedener Strukturen unterstützen möchte (Polymorphie ausnutzen) RT (ICS @ UIBK) Programmiermethodik 544/613 Entwurfsmuster Verhaltensmuster Struktur «interface» Aggregate «interface» Iterator «use» Iterator Client «use» +createIterator() +first() +next() +isDone() +currentItem() ConcreteIterator ConcreteAggregate «use» +createIterator() +first() +next() +isDone() +currentItem() return new ConcreteIterator(this) RT (ICS @ UIBK) Programmiermethodik 545/613 Entwurfsmuster Verhaltensmuster Iterator • Beteiligte Akteure • Iterator • Definiert Schnittstelle für Zugriff und Traversieren • ConcreteIterator • Implementiert Schnittstelle • Verwaltet aktuelle Position beim Traversieren • Aggregate • Definiert Schnittstelle für Erzeugung eines Iterators • ConcreteAggregate • Implementiert Schnittstelle für Erzeugung eines konkreten Iterators • Zusammenspiel • Konkreter Iterator verwaltet Traversieren und kann Nachfolger des aktuellen Elements berechnen • Konsequenzen • Unterschiedliche Traversierungsvarianten werden unterstützt • Iteratoren vereinfachen Schnittstelle • Es können gleichzeitig mehrere Traversierungen stattfinden • Aber erhöhte Laufzeit- und Speicherkosten RT (ICS @ UIBK) Programmiermethodik 546/613 Entwurfsmuster Verhaltensmuster Iterator: Implementierung • Wer kontrolliert das Iterieren? • Externer Iterator • Im Klienten, flexibler, mehrere Operationen (hasNext, next, etc.) • Interner Iterator • Im Iterator, Klient kann nur eine Operation für alle Elemente ausführen lassen • Wer definiert den Algorithmus? • Der Iterator ⇒ besser für unterschiedliche Variationen, unterläuft aber Kapselung • Die Sammlung selbst ⇒ Iterator verwaltet nur den aktuellen Zustand beim Traversieren • Umgang mit Modifikationen • Robuste Iteratoren erlauben Einfügen/Löschen (Kein Einfluss auf Traversierung, keine Kopie der Sammlung notwendig) • Erweiterung der Schnittstelle ( previous (), etc.) • Privilegierte Iteratoren (nicht auf alle Elemente zugreifen) • Iteratoren für Kompositum (interner Iterator einfacher) RT (ICS @ UIBK) Programmiermethodik 547/613 Entwurfsmuster Verhaltensmuster Iterator • Beispielcode • Java Collection-Framework • Über die iterator ()-Methode • Beispiel mit Composite-Pattern p u b l i c c l a s s ComplexPart extends P a r t { p r i v a t e f i n a l L i s t <Part > p a r t s ; ... p u b l i c double g e t P r i c e ( ) { double sum = 0 . 0 ; f o r ( I t e r a t o r <Part > i = p a r t s . i t e r a t o r ( ) ; i . h a s N e x t ( ) ; ) sum += i . n e x t ( ) . g e t P r i c e ( ) ; r e t u r n sum ; } ... } • Querverweise • Kompositum (siehe Implementierung) RT (ICS @ UIBK) Programmiermethodik 548/613 Entwurfsmuster Verhaltensmuster Beobachter • Name • Beobachter (engl.: Observer, Synonyme: Dependent, Publish-Subscribe) • Zweck • Definition einer 1-zu-n Beziehung zwischen Objekten, damit Zustandsänderung eines Objekts (Subjekt, Observable) an alle abhängigen Objekte (Beobachter, Observer) automatisch weitergeleitet wird • Motivation • Wie implementiert man 1-zu-n Beziehung zwischen Objekten • Wenn Objekt seinen Zustand ändert, dann sollen alle anderen Objekte automatisch ein Update erhalten • Objekt, das Daten erzeugt, sollte nicht von den anderen Objekten abhängen RT (ICS @ UIBK) Programmiermethodik 549/613 Entwurfsmuster Verhaltensmuster Beobachter • Motivation (Beispiel) • Wir verwalten mehrere Werte • Wir wollen Werte auf unterschiedliche Art und Weise darstellen • Alle Komponenten sollen immer die gleichen Daten darstellen RT (ICS @ UIBK) Programmiermethodik 550/613 Entwurfsmuster Verhaltensmuster Beobachter • Motivation (Lösung) • Beobachtetes Objekt/Subjekt (Subject, Observable) bietet Mechanismus, um Beobachter (Observers) an- und abzumelden und diese über Änderungen zu informieren • Anwendbarkeit • Wenn Änderung eines Objekts Änderungen in anderen Objekten nach sich zieht, und man Anzahl der abhängigen Objekte nicht von vornherein kennt • Wenn ein Objekt anderen Objekten Nachrichten schicken muss und dabei keine Annahmen über die Art dieser Objekte treffen möchte • Man will lose Kopplung erreichen RT (ICS @ UIBK) Programmiermethodik 551/613 Entwurfsmuster Verhaltensmuster Beobachter: Struktur Subject «interface» Observer -observers +register(o : Observer) +unregister(o : Observer) +notify() +update() ... for all o in observers: o.update() ... ConcreteSubject ConcreteObserver -subjectState +getState() +setState(...) -observerState -subject +update() ... observerState = subject.getState() ... RT (ICS @ UIBK) Programmiermethodik 552/613 Entwurfsmuster Verhaltensmuster Beobachter • Beteiligte Akteure • Subject • Kennt seine Beobachter (Observer), die Anzahl der Beobachter ist aber nicht festgelegt • Stellt Schnittstelle für Hinzufügen, Entfernen und Benachrichtigen von Beobachtern zur Verfügung • Observer • Definiert Schnittstelle für das Aktualisieren der Beobachter • ConcreteSubject • Speichert relevanten Zustand • Verschickt Benachrichtigungen an Beobachter bei Zustandsänderung • ConcreteObserver • Verwaltet Referenz auf ConcreteSubject • Speichert Zustand, der mit Zustand des Subjekts konsistent sein sollte • Implementiert entsprechende Schnittstelle für Beobachter RT (ICS @ UIBK) Programmiermethodik 553/613 Entwurfsmuster Verhaltensmuster • Zusammenspiel • ConcreteSubject benachrichtigt Beobachter bei jeder Zustandsänderung, die den gespeicherten Zustand bei den Beobachtern in inkonsistent Zustand bringen könnte • ConcreteObserver kann nach Benachrichtigung die Zustandsänderung abfragen und seinen gespeicherten Zustand aktualisieren • ConcreteObserver kann Zustandsänderung im ConcreteSubject auslösen • Wartet aber auf Benachrichtigung und ändert erst dann den lokal gespeicherter Zustand RT (ICS @ UIBK) Programmiermethodik 554/613 Entwurfsmuster Verhaltensmuster Beobachter • Vorteile • Abstrakte (minimale) Kopplung zwischen beobachteten Objekt und Beobachtern • Subjekt und Beobachter können auch ohne jeweils andere Komponente in neuen Umgebungen verwendet werden • Beobachter können ohne Änderung des Subjekts hinzugefügt werden • Subjekt und Beobachter können sich auf unterschiedlichen Abstraktionsstufen befinden • Unterstützung von Multicasting • Mehrere Observer können gleichzeitig benachrichtigt werden RT (ICS @ UIBK) Programmiermethodik 555/613 Entwurfsmuster Verhaltensmuster Beobachter • Nachteile • Hohe Änderungskosten • Viele Beobachter • Eine Aktualisierung kann viele weitere Aktualisierungen in anderen Objekten nach sich ziehen • Zusätzliches Protokoll bei Zustandsänderung, wenn man genauere Informationen haben möchte • Probleme bei Zustandsänderung während einer Aktualisierung RT (ICS @ UIBK) Programmiermethodik 556/613 Entwurfsmuster Verhaltensmuster Beobachter • Implementierung • Effiziente Zuordnung von Subjekten und Beobachtern • Einfache Variante: Subjekt verwaltet seine Beobachter • Nicht immer effizient (z.B. viele Subjekte und wenige Beobachter) • Alternative: globale Map “Subject → Observers” • Mehrere Subjekte beobachten • Erweiterung der Schnittstelle (update(Object subj) mit Referenz auf konkretes Subjekt) • Wer löst die Aktualisierung aus (wer ruft notify () auf)? • Subjekt: einfach, aber umständlich (bei jeder Änderung aufrufen) • Beobachter / Applikation: flexibler (Beobachter kann warten, notify () erst nach Serie von Änderungen), aber zusätzliche Verantwortung • Dangling Reference • Wenn Subjekt gelöscht wird, dann müssen Beobachter darüber informiert werden • Konsistenz im Subjekt selbst sicherstellen • 2 Varianten (Push , Pull) RT (ICS @ UIBK) Programmiermethodik 557/613 Entwurfsmuster Verhaltensmuster Beobachter: Push-Variante RT (ICS @ UIBK) Programmiermethodik 558/613 Entwurfsmuster Verhaltensmuster Beobachter: Pull-Variante RT (ICS @ UIBK) Programmiermethodik 559/613 Entwurfsmuster Verhaltensmuster Beobachter: Implementierung • Push-Variante • Beobachter bekommt Zustandsänderung mit Benachrichtigung • Information wird zum Beobachter “geschickt” • Aktualisierung kann bestimmte Parameter bekommen • Pull-Variante • Beobachter bekommt nur Benachrichtigung, dass Zustandsänderung aufgetreten ist • Beobachter muss Zustandsänderung selbst abfragen (Subjekt kontaktieren) • Subjekt muss entsprechende Methoden anbieten • Datenvolumen • Push: groß bis sehr groß • Pull: geringer RT (ICS @ UIBK) Programmiermethodik 560/613 Entwurfsmuster Verhaltensmuster Beobachter: Implementierung • Erweiterung der Schnittstelle für bestimmte Änderungen (Ereignisse) • Wenn bestimmtes Ereignis eintritt, dann werden nur entsprechenden Beobachter informiert • Kapselung komplexer Aktualisierungssemantik • Für komplexe Beziehungen zwischen mehreren Subjekten und Beobachtern kann man Aktualisierungsklasse dazwischen schalten (ChangeManager) • Verwaltet Zuordnung zwischen Subjekten und Beobachtern • Definiert Aktualisierungsstrategie • Aktualisiert alle abhängigen Beobachter bei Nachricht eines Subjekt • Subjekt und Beobachter in einer Klasse implementieren • Abhängig von Spracheneigenschaften • Beispiel Smalltalk • Subjekt- und Beobachterschnittstelle werden im Wurzelobjekt Object implementiert RT (ICS @ UIBK) Programmiermethodik 561/613 Entwurfsmuster Verhaltensmuster Beobachter • Beispielcode (siehe Beispiel ObserverClient.java) • Querverweise • Singleton und Mediator (ChangeManager) RT (ICS @ UIBK) Programmiermethodik 562/613 Entwurfsmuster Verhaltensmuster Beispiel: Unterstützung in Java public interface Observer { void update ( Observable o , Object arg ) ; } public class Observable { ... p u b l i c O b s e r v a b l e ( ) {} public synchronized void addObserver ( Observer o ) { . . public synchronized void d e l e t e O b s e r v e r ( Observer o ) public void n o t i f y O b s e r v e r s ( ) { . . . } public void n o t i f y O b s e r v e r s ( Object arg ) { . . . } public synchronized void d e l e t e O b s e r v e r s ( ) { . . . } protected synchronized void setChanged ( ) { . . . } protected synchronized void clearChanged ( ) { . . . } p u b l i c s y n c h r o n i z e d boolean hasChanged ( ) { . . . } public synchronized i n t c o u n t O b s e r v e r s ( ) { . . . } } RT (ICS @ UIBK) Programmiermethodik 563/613 Entwurfsmuster Verhaltensmuster Probleme (Java-spezifisch) • Potentielles Subjekt (Observable) erbt schon von anderer Klasse • Keine Mehrfachvererbung in Java ⇒ Delegation benutzen • Potentielles Subjekt beinhaltet eigentliches Subjekt • Aufrufe werden weitergeleitet • Delegate-Objekt muss Observable entsprechend überschreiben • setChanged und clearChanged müssen dabei Zugriffsmodifikator public bekommen, damit Aufrufe entsprechend weitergeleitet werden können RT (ICS @ UIBK) Programmiermethodik 564/613 Entwurfsmuster Verhaltensmuster Weitere Verhaltensmuster • Interpreter • Definiert für gegebene Sprache eine Repräsentation der Grammatik sowie einen Interpreter, der die Repräsentation nutzt, um Sätze in der Sprache zu interpretieren • Schablonenmethode • Definiert Skelett eines Algorithmus in einer Operation und delegiert einzelne Schritte an Unterklassen • Befehl • Kapselt Befehl als Objekt • Besucher • Kapselt eine auf Elementen einer Objektstruktur auszuführende Operation als Objekt (Analogie zum internen Iterator) • Memento • Erfasst und externalisiert internen Zustand eines Objekts ohne seine Kapselung zu verletzen, so dass Objekt später in diesen Zustand zurückversetzt werden kann RT (ICS @ UIBK) Programmiermethodik 565/613 Entwurfsmuster Verhaltensmuster Weitere Verhaltensmuster • Strategie • Definiert Familie von Algorithmen, kapselt jeden einzelnen und macht sie austauschbar • Vermittler • Definiert Objekt, welches Zusammenspiel einer Menge von Objekten in sich kapselt • Zustand • Ermöglicht Objekt, sein Verhalten zu ändern, wenn interner Zustand sich ändert • Zuständigkeitskette • Vermeidet Kopplung eines Auslösers einer Anfrage an Empfänger, indem mehr als ein Objekt die Möglichkeit erhält, die Anfrage zu erledigen • Verkettet empfangenen Objekte, und leitet die Anfrage an Kette entlang, bis ein Objekt sie erledigt RT (ICS @ UIBK) Programmiermethodik 566/613 Entwurfsmuster Verhaltensmuster Zusammenfassung • Entwurfsmuster • Entwurfsmuster beschreibt Problem, welches immer wieder auftritt • Es beschreibt allgemeinen Kern der Lösung • Muster kann dann zum Lösen eines neuen Problems verwendet werden • Nutzen von Entwurfsmustern • Objekte / Klassen identifizieren • Nicht nur 1:1-Abbildung der realen Welt schaffen • Für zukünftige Änderungen vorbereiten • Granularität der Objekte festlegen • Schnittstellen identifizieren • Beziehungen zwischen Schnittstellen festlegen und Implementierung auswählen • Design-Grundprinzipien berücksichtigen • Implementierungen austauschbar machen • Objekterzeugung änderbar gestalten • Funktionalität änderbar gestalten RT (ICS @ UIBK) Programmiermethodik 567/613 GUI-Programmierung in Java Übersicht GUI-Programmierung in Java Überblick Komponenten und Container Layout Ereignisbasierte Programmierung RT (ICS @ UIBK) Programmiermethodik 568/613 GUI-Programmierung in Java Überblick Übersicht GUI-Programmierung in Java Überblick Komponenten und Container Layout Ereignisbasierte Programmierung RT (ICS @ UIBK) Programmiermethodik 569/613 GUI-Programmierung in Java Überblick GUI • GUI = Graphical User Interface • Grafische Benutzeroberfläche • Steuerung der Anwendung durch Maus- und Tastatur mit Hilfe von GUI-Komponenten (Fenster, Buttons, Slider, Scrollbar etc.) • Wichtige Konzepte bei der GUI-Programmierung • Komponenten • Hierarchische Anordnung der einzelnen Komponenten • Layout • Layout-Manager unterstützen Anordnung der einzelnen Komponenten am Bildschirm • Ereignisgesteuerte Programmierung • Komponenten haben eigene Funktionalität • Komponenten reagieren auf Ereignisse (Events) • Abfolge der Benutzereingaben bestimmt Programmablauf RT (ICS @ UIBK) Programmiermethodik 570/613 GUI-Programmierung in Java Überblick GUI-Programmierung in Java • Java 1.0: Abstract Windowing Toolkit • Bestandteil der Java API • Minimalistisch • Spezifisch (OS) • Low-level Programmierung • Java 1.2: Swing (leichtgewichtige Komponenten) • Basiert auf AWT • Bestandteil der Java Foundation Classes (JFC) • JFC ist Sammlung von Programmierschnittstellen (APIs) zur Erstellung portabler Java GUIs • Plattformunabhängig • Bessere Performance • Wird in dieser Vorlesung besprochen • Alle praktischen Beispiele und Abbildungen wurden dem Java Tutorial entnommen: http://docs.oracle.com/javase/tutorial/uiswing/ RT (ICS @ UIBK) Programmiermethodik 571/613 GUI-Programmierung in Java Überblick Java Swing • Viele Komponenten • Leichtgewichtig (direkt von Java gerendert) • Auf allen Plattformen sehen Komponenten gleich aus • Look-and-Feel (Erscheinungsbild) konfigurierbar • Windows, Motif, Metal, Nimbus • Einige Komponenten zusätzlich zu AWT • Drag and Drop • Tooltips • Automatisches Double Buffering • Code der Bibliotheksklassen ruft Programmcode des Anwendungsprogrammierers auf, wenn entsprechendes Grafikelement bei Programmausführung benutzt wird (z.B. Mausklick) RT (ICS @ UIBK) Programmiermethodik 572/613 GUI-Programmierung in Java Komponenten und Container Übersicht GUI-Programmierung in Java Überblick Komponenten und Container Layout Ereignisbasierte Programmierung RT (ICS @ UIBK) Programmiermethodik 573/613 GUI-Programmierung in Java Komponenten und Container Grundlagen • GUI wird aus einzelnen Komponenten aufgebaut • Container (spezielle Komponenten) können weitere Komponenten enthalten und anordnen • Alle Container sind auch wieder Komponenten ⇒ Kompositum • Container auf oberster Hierarchiestufe basieren auf AWT-Containern (schwergewichtig) • Leichtgewichtige Komponenten erben von JComponent • JComponent ist Basisklasse für die meisten Swing-Komponenten (Frames, Buttons etc.) • Stellt Infrastruktur zum Zeichnen der Komponenten zur Verfügung • API lesen RT (ICS @ UIBK) Programmiermethodik 574/613 GUI-Programmierung in Java Komponenten und Container Swing-Komponenten RT (ICS @ UIBK) Programmiermethodik 575/613 GUI-Programmierung in Java Komponenten und Container Swing-Komponenten RT (ICS @ UIBK) Programmiermethodik 576/613 GUI-Programmierung in Java Komponenten und Container Swing-Komponenten (Container) RT (ICS @ UIBK) Programmiermethodik 577/613 GUI-Programmierung in Java Komponenten und Container Container und Komponenten • Top-Level Container in Swing • Können weitere Komponenten enthalten und anordnen • Stellen Infrastruktur zum Zeichnen von Komponenten und zur Ereignisbehandlung bereit • Es gibt vier solche Container: JFrame, JDialog, JWindow, JApplet • Container-Komponenten • Können wie Top-Level Container weitere Komponenten enthalten und anordnen • Bestimmen Größe und Position jeder Komponente • Container in Swing: JScrollPane, JTabbedPane, . . . • Basiskomponenten • Benutzer interagiert mit diesen Komponenten • Beispiele: JComboBox, JTextField, JTable, . . . RT (ICS @ UIBK) Programmiermethodik 578/613 GUI-Programmierung in Java Komponenten und Container Aufbau • Verwendete Komponenten lassen sich in Hierarchie anordnen • Wurzel ist immer ein Top-level Container • Top-level Container wird mit Fenster verbunden • In diesem Fenster werden seine (sichtbaren) Komponenten dargestellt • Swing-Hauptfenster enthält eine Hauptkomponente (RootPane), die alle anderen Komponenten aufnimmt • RootPane enthält folgende Komponenten • Eine GlassPane • Eine LayeredPane • LayeredPane enthält ihrerseits zwei Unterkomponenten • Eine ContentPane • Eine Menüleiste RT (ICS @ UIBK) Programmiermethodik 579/613 GUI-Programmierung in Java Komponenten und Container Aufbau • LayeredPane und GlassPane liegen „übereinander“ und füllen Fenster jeweils komplett aus • GlassPane ist normalerweise durchsichtig und wird meist nicht zur Grafikausgabe benutzt • Kann verwendet werden, um Effekte zu erzielen, die das Fenster als Ganzes betreffen • LayeredPane enthält Menü und Dialogelemente der Anwendung • Einfügen und Anordnen von Dialogelementen auf einem Hauptfenster erfolgt über dessen ContentPane RT (ICS @ UIBK) Programmiermethodik 580/613 GUI-Programmierung in Java Komponenten und Container Komponenten zu Containern hinzufügen • Mit add-Methode werden Komponenten zu einem Container hinzugefügt (und damit zu Kindern des Containers in der Komponentenhierarchie) • Ein Argument der add-Methode spezifiziert die hinzuzufügende Komponente • Achtung: Eine Komponente kann immer nur zu einem Container gehören • Wird Komponente zu einem zweiten Container hinzugefügt, dann wird diese Komponente aus dem ersten Container entfernt RT (ICS @ UIBK) Programmiermethodik 581/613 GUI-Programmierung in Java Komponenten und Container JFrame • Java GUI-Applikationen benutzen oft JFrame, um ein Hauptfenster zu öffnen • JFrame = einfaches, größenänderbares Fenster mit Rand, Titelleiste und optionaler Menüleiste • JFrame bildet Bindeglied zwischen Swing und Betriebssystem • JFrame registriert sich als Fenster im Betriebssystem und kann wie herkömmliches Fenster benutzt werden • Unterstützt Methoden zum • Lesen/Setzen des Titels, • Lesen/Setzen des Zustands, • Sichtbarkeit eines Frames, • Lesen/Setzen der Position, • Lesen/Setzen der Größe • Hinzufügen einer Komponente etc. RT (ICS @ UIBK) Programmiermethodik 582/613 GUI-Programmierung in Java Komponenten und Container JLabel, JButton, JTextField • JLabel • Einfache Komponente zum Beschreiben anderer Komponenten • Unterstützt Methoden für • • • • Lesen/Setzen des Labels Lesen/Setzen der Position (horizontal/vertikal) Anbinden an eine Komponente (setLabelFor) ... • JButton • Die einfachste Komponente für die Interaktion (Anklicken) • Bei einer Interaktion wird entsprechender Code ausgeführt • Muss vom Programmierer bereitgestellt werden (Events) • Methoden für das Verändern sind sehr ähnlich zu denen von JLabel • JTextField • Einfachste Textkomponente in Swing (Texteingabe) • Lesen/Setzen des Textes in der Komponente RT (ICS @ UIBK) Programmiermethodik 583/613 GUI-Programmierung in Java Komponenten und Container Ein einfaches Swing-Programm (Nicht Thread-safe) import j a v a x . s w i n g . ∗ ; public class HelloWorldSwing { p r i v a t e s t a t i c v o i d createAndShowGUI ( ) { // C r e a t e and s e t up t h e window . JFrame f r a m e = new JFrame ( " HelloWorldSwing " ) ; f r a m e . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT_ON_CLOSE ) ; // Add t h e u b i q u i t o u s " H e l l o World " l a b e l . J L a b e l l a b e l = new J L a b e l ( " Hello World " ) ; l a b e l . s e t V e r t i c a l A l i g n m e n t ( S w i n g C o n s t a n t s . CENTER ) ; f r a m e . g e t C o n t e n t P a n e ( ) . add ( l a b e l ) ; // D i s p l a y t h e window . f r a m e . pack ( ) ; frame . s e t V i s i b l e ( true ) ; } p u b l i c s t a t i c v o i d main ( f i n a l S t r i n g [ ] a r g s ) { createAndShowGUI ( ) ; // . . . w e i t e r e r Code RT (ICS @ UIBK) Programmiermethodik 584/613 GUI-Programmierung in Java Komponenten und Container Beispiel: TopLevelDemo • Programm findet man unter http://docs.oracle.com/javase/ tutorial/uiswing/components/toplevel.html • Aufbau • Hierarchie (Containment hierarchy) der Komponenten RT (ICS @ UIBK) Programmiermethodik 585/613 GUI-Programmierung in Java Layout Übersicht GUI-Programmierung in Java Überblick Komponenten und Container Layout Ereignisbasierte Programmierung RT (ICS @ UIBK) Programmiermethodik 586/613 GUI-Programmierung in Java Layout Layout-Manager • Zu jedem Container gibt es Layout-Manager • Durch diesen werden Komponenten im Container angeordnet • Dieser bestimmt Größe und Position jeder Komponente • Mit setLayout-Methode kann Layout-Manager bestimmt werden • Dieser übernimmt das Platzieren aller Komponenten, die mit nachfolgenden add-Aufrufen hinzugefügt werden • Argumente der add-Methode hängen vom Layout-Manager ab • Alle JPanel-Objekte benutzen standardmäßig den FlowLayout Manager • Alle ContentPanes (die Container in JApplet, JDialog, JFrame) benutzen standardmässig den BorderLayout-Manager • Layout-Manager kann auf null gesetzt werden • Dann kann man Komponenten explizit platzieren RT (ICS @ UIBK) Programmiermethodik 587/613 GUI-Programmierung in Java Layout Verfügbare Layout-Manager RT (ICS @ UIBK) Programmiermethodik 588/613 GUI-Programmierung in Java Layout Beispiel: BorderLayout • BorderLayout-Objekt hat 5 Teile (Konstanten) • PAGE_START, PAGE_END, LINE_START, LINE_END, CENTER • CENTER bekommt am meisten Platz, der Rest passt sich an • Beispiel • http://docs.oracle.com/javase/tutorial/uiswing/layout/ border.html • Komponenten werden zu einem Frame hinzugefügt • ContentPane benutzt automatisch BorderLayout RT (ICS @ UIBK) Programmiermethodik 589/613 GUI-Programmierung in Java Layout Beispiel: GridLayout • Beim GridLayout werden Komponenten in einem Gitter von Zellen angeordnet • Jede Komponenten verbraucht gesamten Platz in einer Zelle • Wird Fenstergröße verändert, dann wird jede Zellengröße entsprechend angepasst • Beispiel • http://docs.oracle.com/javase/tutorial/uiswing/layout/ grid.html RT (ICS @ UIBK) Programmiermethodik 590/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Übersicht GUI-Programmierung in Java Überblick Komponenten und Container Layout Ereignisbasierte Programmierung RT (ICS @ UIBK) Programmiermethodik 591/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Ereignisbasierte Programmierung • Kontrollfluss eines Systems wird durch Ereignisse und nicht durch Kontrollstrukturen oder Funktionsaufrufe bestimmt • Beispiele für Ereignisse • Mausklick • Eingabe per Tastatur • ... • Typische Anwendung • Interaktive Systeme • Interaktion zwischen Benutzer und grafischer Benutzerschnittstelle • Programmierung von Sensoren • Messwerte bestimmen weiteren Ablauf RT (ICS @ UIBK) Programmiermethodik 592/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Generelle Idee • Zuhörer (Listener) registrieren sich für bestimmte Ereignisse • Quelle schickt Benachrichtigung, wenn ein Ereignis eintritt register Listener Listener Listener Listener Listener Event Source notify RT (ICS @ UIBK) Programmiermethodik 593/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Entwurfsmuster? • Teilnehmer • Event-Source (Quelle) • Event-Listener (registriert sich bei der Quelle) • Event-Objekt (wird zum Listener geschickt) • Rollen • Source = Subjekt • Listener = Beobachter • Push-Variante besser • Listener kann sich bei mehreren Quellen registrieren • Alle Quellen benutzen gleiche Methode (Callback-Methode) für Benachrichtigungen • Beobachter sollten sofort reagieren RT (ICS @ UIBK) Programmiermethodik 594/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Event-Objekte • Ereignis wird durch Objekt repräsentiert • Es gibt unterschiedliche Ereignistypen, von denen Objekte angelegt werden können • Ereignistypen erben von AWTEvent • Ereignisse werden meist von Komponenten erzeugt • Ereignisobjekt beinhaltet Informationen über • das Ereignis sowie • die Quelle des Ereignisses • Typische Verarbeitung • Endlosschleife (Event-Schleife), in der Ereignisse generiert werden • Interne Verwaltung eines Puffers für einzelne Ereignisse (Event-Warteschlange) • Kontrollfluss der Event-Schleife sollte unabhängig vom Kontrollfluss der Empfänger sein RT (ICS @ UIBK) Programmiermethodik 595/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Listener • Möchte Objekt von einer Komponente über bestimmtes Ereignis benachrichtigt werden, dann muss • Komponente ein passendes Interface implementieren und • Object sich als Listener bei der Komponente (Source) registrieren • Implementieren eines passenden Interfaces bedeutet, Methode zur Verfügung zu stellen, die Ereignis behandeln kann • Implementierung wird als Event Handler bezeichnet • Oft als innere (anonyme) Klasse implementiert • In Swing gibt es große Anzahl an Listener-Interfaces • Manche Interfaces haben noch zusätzliche Adapter-Klassen, die für größere Interfaces “Implementierungen” bereitstellen (man muss nur davon ableiten und benötigte Funktionalität implementieren) • Liste der Listener-APIs: http: //docs.oracle.com/javase/tutorial/uiswing/events/api.html RT (ICS @ UIBK) Programmiermethodik 596/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Listener-Interfaces (mit Beispielen) • ActionListener • Benutzer klickt z.B. Button an, drückt Enter-Taste in Textfeld oder wählt Menüeintrag aus • WindowListener • Benutzer öffnet / schließt Fenster • MouseListener • Benutzer klickt Maustaste während Mauszeiger über einer Komponente ist • MouseMotionListener • Benutzer bewegt Maustaste über einer Komponente • ComponentListener • Komponente wird sichtbar • FocusListener • Komponente bekommt Focus RT (ICS @ UIBK) Programmiermethodik 597/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Beispiel – Mausklick auf Button • Mausklick führt dazu, dass Button Ereignis vom Typ ActionEvent erzeugt • Dieses Ereignis(-Objekt) hat alle Informationen über das Ereignis und seine Quelle, sowie Beschreibung der ausgeführten Aktion • Dieses Ereignis wird an alle bei dem Button registrierten ActionListener -Objekte geschickt • Jeder Listener implementiert Methode zur Ereignisbehandlung • In diesem Fall wird mit Methode actionPerformed festgelegt, was beim Eintreten des Ereignisses passieren soll • Damit ruft somit Button bei einer Aktion (Mausklick) diesen Code auf RT (ICS @ UIBK) Programmiermethodik 598/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Registrieren • Ein Listener muss explizit mit dem Ereignisauslöser verbunden werden • Dafür gibt es unterschiedliche Methoden der Form addEventListener( EventListener ) • Nicht jede Komponente kann jedes Ereignis auslösen • Daher gibt es entsprechende add-Methoden nur für Ereignisse, die die Komponenten tatsächlich auslösen • JFrame-Klasse bietet zum Beispiel addWindowListener() für Fensterereignisse, aber kein addActionListener () • Ein JButton hingegen bietet addActionListener () an, damit er die Aktivierung der Schaltfläche melden kann • So lassen sich über die angebotenen add-Methoden gut die Ereignisse ablesen, die eine Komponente auslösen kann RT (ICS @ UIBK) Programmiermethodik 599/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Beispiel für mehrere Listener • Beispiele für mehrere Listener-Implementierungen ( ActionListener ) • http://docs.oracle.com/javase/tutorial/uiswing/events/ actionlistener.html • ActionListener : Einfachste und am meisten benutzte Variante RT (ICS @ UIBK) Programmiermethodik 600/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Aktionen • Action-Objekt ist ein ActionListener • Damit werden Zustand und Funktionalität einer Komponente getrennt • Action-Objekt wird mit Methode setAction zu Komponente hinzugefügt • Zustand der Komponente wird dem Zustand des Action-Objektes angeglichen • Action-Objekt wird als ActionListener bei Komponente registriert • Wenn sich der Zustand des Action-Objektes ändert, wird der Zustand der Komponente ebenfalls geändert • Um ein Action-Objekt zu erzeugen, leitet man Klasse von der Klasse AbstractAction ab • Unterklasse muss Methode actionPerformed implementieren, da Action-Objekt auch als ActionListener fungiert • Beispiel • http://docs.oracle.com/javase/tutorial/uiswing/misc/ action.html RT (ICS @ UIBK) Programmiermethodik 601/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Event Dispatching Thread (EDT) • Ereignisbehandlung erfolgt immer im Event Dispatching Thread • Ein Event-Handler nach dem anderen (Event-Warteschlange) • Auch die Zeichenroutinen der Komponenten laufen im Event Dispatching Thread ab • Während Event-Handler abgearbeitet wird, ist GUI “eingefroren” (reagiert nicht) RT (ICS @ UIBK) Programmiermethodik 602/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Regeln zum Umgang mit EDT • Ändere Zustand einer Komponente nicht während Zeichenroutine • Grund: Änderung führt zum repaint ()-Event, welches wiederum zur Änderung führt, . . . ⇒ Event-Warteschlange wird immer weitere repaint ()-Events erhalten und zu 100 % CPU-Last führen • Führe keinen langfristigen Berechnungen mit EDT durch • Grund: Event Abarbeitung friert GUI ein, sollte nicht zu lange dauern • Lösung: Führe Berechnungen asynchron in extra Thread aus (siehe auch http://docs.oracle.com/javase/tutorial/uiswing/ concurrency/worker.html) • Ändere niemals den GUI-Zustand außerhalb des EDTs • Grund: EDT ändert GUI-Zustand und Swing ist nicht Thread-safe • Lösung: Führe Änderung mittels javax .swing. SwingUtilities . invokeLater (...) aus • Nicht-Befolgung dieser Regeln kann folgende Konsequenzen haben • Visuelle Artefakte • Unnötige CPU Belastung • “Langsame” bis hin zu vollständig eingefrorener GUI RT (ICS @ UIBK) Programmiermethodik 603/613 GUI-Programmierung in Java Ereignisbasierte Programmierung Model-View-Controller (MVC) • Anstatt den gesamten Code in einzelne Klasse zu packen, werden beim MVC-Konzept drei unterschiedliche Bestandteile eines grafischen Elements unterschieden • Modell enthält Daten des Dialogelements und speichert seinen Zustand • View ist für grafische Darstellung der Komponente verantwortlich • Controller wirkt als Verbindungsglied zwischen beiden. Er empfängt Tastatur- und Mausereignisse und stößt erforderliche Maßnahmen zur Änderung von Model und View an • Vorteil von MVC • Austauschbarkeit der einzelnen Komponenten, hohe Kohäsion • Bei Swing-Dialogelementen wird vereinfachte Variante von MVC verwendet (Model-Delegate-Prinzip) • Dabei wird die Funktionalität von View und Controller in einem UI Delegate zusammengefasst • Dadurch wird die Komplexität reduziert und die in der Praxis oft unhandliche Trennung zwischen View und Controller aufgehoben RT (ICS @ UIBK) Programmiermethodik 604/613 Ausblick Übersicht Ausblick Reflexion Java 8 RT (ICS @ UIBK) Programmiermethodik 605/613 Ausblick Reflexion Übersicht Ausblick Reflexion Java 8 RT (ICS @ UIBK) Programmiermethodik 606/613 Ausblick Reflexion Wo stehen wir aktuell? • Was wurde bisher besprochen? • Objektorientierung allgemein • Grundlegende Programmierung in Java • Objektorientierung in Java • Einige Details von Java • Entwurfsmuster • GUI-Programmierung • Wie geht es weiter? • Einsatz, Vertiefung und Erweiterung der besprochenen Konzepte in weiteren Lehrveranstaltungen • Entwurf von Softwaresystemen • Softwareentwicklung und Projektmanagement • Abgrenzung der Konzepte, alternative Programmier-Paradigmen • Funktionale Programmierung • Logische Programmierung • Abgrenzung der Konzepte, formale Spezifikation und Beweise anstelle von textueller Schnittstellen-Dokumentation und Unit-Tests • Logik • Interaktives Beweisen RT (ICS @ UIBK) Programmiermethodik 607/613 Ausblick Reflexion Und für die Praxis? • Java ist eine weitverbreitete Programmiersprache • Kommerzielle Software • Open-Source-Projekte • Typische Einsatzgebiete • Web-Programmierung • Größere plattformunabhängige Projekte • Web-Service-Programmierung • ... • Unterschiedliche Technologien • Java SE (Standard Edition) • In dieser Vorlesung behandelt • Java EE (Enterprise Edition) • Industriestandard für die Implementierung von unternehmensspezifischen Service-Oriented-Architecture-Applikationen und Web-Applikationen • Java ME (Micro Edition) • Mobile und eingebettete Systeme (Handy, PDA, Set-top-Boxen, Drucker etc.) RT (ICS @ UIBK) Programmiermethodik 608/613 Ausblick Reflexion Verbreitung • Verbreitung von Sprachen lässt sich nur schwer messen • Verschiedene Ansätze • Nicht wissenschaftlich • Nur grobe Abschätzung/Richtung • Beispiele • Language Popularity Web-Seite • Benutzung bekannter Suchmaschinen • http://www.langpop.com/ • TIOBE Programming Community Index • Wird jeden Monat aktualisiert • Berechnung: “The ratings are based on the number of skilled engineers world-wide, courses and third party vendors. The popular search engines Google, MSN, Yahoo!, Wikipedia and YouTube are used to calculate the ratings.” RT (ICS @ UIBK) Programmiermethodik 609/613 Ausblick Reflexion TIOBE (Trend Juni 2013, Top 10) RT (ICS @ UIBK) Programmiermethodik 610/613 Ausblick Java 8 Übersicht Ausblick Reflexion Java 8 RT (ICS @ UIBK) Programmiermethodik 611/613 Ausblick Java 8 Ausblick auf Java 8 • Lambda Expressions (Closures, Project Lambda) • Sprachmittel, das aus der funktionalen Programmierung stammt • Funktionen können als Parameter / Rückgabewert von Methoden verwendet werden • Beispiele: (int x, int y) -> x + y () -> 42 (String s) -> { System.out.println(s); } • Beispiel • Heute b u t t o n . a d d A c t i o n L i s t e n e r ( new A c t i o n L i s t e n e r ( ) { public void actionPerformed ( ActionEvent e ) { ui . dazzle (e . getModifiers ()); } }); • Java 8 (geplant) b u t t o n . a d d A c t i o n L i s t e n e r ( e −> u i . d a z z l e ( e . getModifiers ())); RT (ICS @ UIBK) Programmiermethodik 612/613 Ausblick Java 8 Ausblick auf Java 8 • Verwendung von Lambdas im Collection-Framework • Zusätzlich bessere Unterstützung der Nebenläufigkeit bei Collections • Parallele Arrays etc. • Typ-Annotationen • Annotationen können überall verwendet werden, wo Typen erlaubt sind • Damit wird es möglich, das Typsystem von Java zu erweitern (Typen mit Annotations beschreiben) • Statische Analysewerkzeuge können davon profitieren • Beispiel Map<@NonNull S t r i n g , @NonEmpty L i s t <@ReadOnly Document>> f i l e s ; @NonNull O b j e c t @ N u l l a b l e [ ] a r r a y ; RT (ICS @ UIBK) Programmiermethodik 613/613