Modellierung und Programmierung 1 Prof. Dr. Sonja Prohaska Computational EvoDevo Group Institut für Informatik Universität Leipzig 20. Januar 2016
Interface Sets<E> M. Meiler
Sortieren der Objekten einer Collection... nur für Listen! Idee 1. wonach sind die Objekte der Liste zu sortieren? 2. wie führt man einen Vergleich zweier Objekte aus? 3. wie erstellt man aus paarweisen Vergleichen eine sortierte Liste? Ein paar Antworten 1. festlegen nach welchen Attributen der Objekte in welcher Reihenfolge sortiert werden soll, um die gewünschte Sortierung zu erzielen 2. ausführen paarweiser Vergleiche 3. verwenden eines, auf Vergleich basierenden, Sortierverfahrens z.b. devide and conquer -Prinzip: Mergesort
Sortieren der Objekten einer Liste Sortieren einer Collection<X> in Java 3. importieren der Klasse Collections stellt die Methode sort() zur Verfügung import java.util.collections; zugrunde liegt ein Mergsort (O(n) = nlog(n)) 2. implementieren des Interfaces Comparable<T> public class X implements Comparable<X> es stellt die Methode compareto() zur Verfügung 1. spezifizieren der Methode compareto() sodass a.comparto(b) > 0, wenn b > a a.comparto(b) = 0, wenn b = a a.comparto(b) < 0, wenn b < a Comparable<T> ist generisch: (T object).compareto(t anotherobject) Attribute der beiden Objekte des Types T vergleichen
Sortieren der Objekten einer Liste Übung: TryVektor.java (Horton s Beginnig Java 7, Chapter 7)
Fehlerbehandlung Kritische Ereignisse, die zum Programmabbruch führen können, werden als Ausnahmen (Exceptions) oder Fehler (Error) behandelt. Exceptions leichte Fehler bzw. besonders seltene, unerwartete Ereignisse nach spezieller Behandlung eines solchen Fehlers kann der Programmablauf fortgesetzt oder ein Abbruch vom Programmierer ausgelöst werden der Programmierer hat es in der Hand manche Fehler müssen behandelt werden (checked exceptions) andere können übergangen werden (unchecked exceptions) Errors schwerwiegende Fehler weiterer Programmablauf ist unmöglich oder nicht mehr sinnvoll sollten immer zum Abbruch des Programms führen der Programmierer sollte den Code gründlich überdenken
Throwables and Exceptions java.lang.throwable verwaltet Ausnahmesituationen Exception ist (wie Error) von Throwable abgeleitet weitere Ableitungen spezifizieren den Typ der Exception Object Throwable Exception Error Exceptions you must catch Errors you should not catch
Fehlerbehandlung Bei Eintritt einer Ausnahme throw Exception (Ausnahme werfen) anlegen eines Objekts einer Unterklasse von Exception Programm unterbrechen catch Exception (Ausnahme abfangen) festgelegte Fehlerbehandlung auslösen und das Programm evtl. fortsetzen Ausnahme weitergeben (passing exception) tritt innerhalb einer Methode eine Ausnahme auf und soll oder kann sie nicht abgefangen werden muss die Methode definieren, dass sie eine Ausnahme werfen kann welche an die aufrufende Methode weitergegeben wird Beispiel: int divide() throws ArithmeticException{ }
try - catch Eine Methode, in der eine Ausnahme geworfen wird, muss die Ausnahme unmittelbar abfangen oder weitergeben. try eine Anweisung, die eine (oder mehrere) Exceptions werfen kann wird von einem try-block umschlossen catch ([ExceptionType] e) im unmittelbaren Anschluss auf den try-block folgt der (erste) catch-block catch (IOException e) {...} weitere catch-block können folgen im Block selbst wird die jeweilige Ausnahme behandelt rethrow e; gibt sie zusätzlich weiter Übung: HandlingExceptions.java, PassingExceptions.java
Exceptions und Polymorphismus catch([exceptiontype] e) catch-parameter: [ExceptionType] e ParameterTyp ExceptionType bzw. ExceptionClass parametername Objekt e der ExceptionType kann (dank Polymorphismus) allgemein über den Typ Exception oder über einen spezifischeren Typ z.b. ArithmeticException angesprochen werden (wichtig wenn Ausnahmen unterschiedlichen Typs möglich sind) e ist der Name des Exception-Objekts tostring(e) liefert Klasse und Fehlermeldung zu e
try - catch - finally finally der finally-block folgt unmittelbar auf den catch-block er wird immer ausgeführt, egal ob im try-block) eine Exception geworfen wurde oder nicht dient im besonderen dem Aufräumen z.b.: beim Schreiben in eine Datei wird diese geschlossen warum nicht einfach if - else? leichter zu sehen, dass es sich um evtl. Fehler handelt, die bearbeitet werden es dient der Behandlung von seltenen Ereignissen vordefinierte, häufige Fehler werden automatisch erkannt und müssen nur abgefangen werde Auslagern der Fehlermeldung
Exception-Klassen erweitern den Programmablauf ensprechend absichern Standard-Fehlermeldungen um Information erweitern aussagekräftige(re) Fehlermeldungen verfassen grosse Rolle bei... Zugriff auf Dateien z.b. Zugriffsrechte, Lese- und Schreibrechte Verarbeiten von Input z.b. Einhaltung von Datenformaten Ausnahmefälle in lange laufenden Programmen so behandeln, dass nicht abgebrochen werden muss (anlegen einer log-datei mit aufgetretenen Fehlern)
Eigene Exception-Klassen die eigene Exception sollte sich von der Klasse Exception ableiten sollte den default Konstruktor haben sollte einen Konstruktor haben, der einen String als Parameter hat (flexibel gestalten der Fehlermeldung der Fehlermeldung) alternativ kann auch tostring() überschrieben werden
Werfen eigener Exceptions im Gegensatz zu vordefinierten Fehlern müssen eigene Exceptions explizit geworfen werden unter der Ausnahmebedingung z.b.: (divisor == 0) wird ein Exception-Objekt der eigenen Exceptionklasse erzeugt und geworfen z.b.: throw new DivisionByZeroException(); Übung: DoubleDivision.java Hinweis: Division durch 0.0 ergibt bei double (+ )infinity oder NaN
Datenströme allgemein programm-externe Eingabedaten (Informationen) Input programm-externe Ausgabedaten (Informationen) Output Kommunikation mit den externen Medien erfordert Ein- und Ausgabemechanismen die Datenströme sind die Schnittstellen Datenströme nehmen Daten in Empfang und leiten sie weiter sie sind gerichtet (Prinzip first-in first-out ) Eingabedatenströme (input streams) Lesen von Daten Ausgabeströme (output streams) Schreiben von Daten INPUT Programm OUTPUT Data (file) Device (e.g. keyboard) InputStream OutputStream Device (e.g. Monitor) Data (file)
Datenströme allgemein Datenströme transportieren Dateneinheiten eine Dateneiheit aufnehmen und weitergeben ungepuffert mehrere Dateneinheiten aufnehmen und gesammelt weitergeben gepuffert Pufferung wirkt sich günstig auf die Performance der Lese- und Schreibgeschwindigkeit aus evtl. negativ auf die Datensicherheit Datenströme können hintereinander geschaltet werden Pipe, Pipeline oder Filter-Stream Dateneinheit Stream ungepuffert Datenziel Dateneinheit Datenquelle Stream gepuffert Datenziel Datenquelle
Datenströme in Java Unterscheidung aus Sicht des Programms in Eingabe- und Ausgabedatenströme Unterscheidung aus Sicht der transportierten Dateneinheiten in Byteströme (8-Bit-Dateneinheit byte) und Zeichenströme (16-Bit-Dateneinheit char) Vier Hierarchien von Klassen in java.io.* InputStream byteorientiertes Lesen OutputStream byteorientiertes Schreiben Reader zeichenorientiertes Lesen Writer zeichenorientiertes Schreiben
Klassenhierarchie der Streams Byteströme (links) und Zeichenströme (rechts) Interfaces AutoClosable Interfaces AutoClosable Closable Readable Closable Appendable close(); read(); close(); append(); Object Object Abstract Classes Abstract Classes InputStream OutputStream Reader Writer read(); read( byte[] array); close(); write(); write( byte[] array); close(); read(); close(); write(); close(); Classes FilterInputStream FilterOutputStream u.a. u.a. Classes u.a. u.a. BufferedInputStream PrintStream BufferedReader BufferedWriter
Standarddatenströme Die Standarddatenströme in, out und err sind Klassenkonstanten der Klasse java.lang.system. System.in Standardeingabedatenstrom Objekt der byteorientierten Klasse InputStream üblicherweise mit der Tastatur verbunden System.out Standardausgabedatenstrom Objekt der byteorientierten Klasse PrintStream üblicherweise mit der Konsole verbunden System.err Standardfehlerausgabedatenstrom Objekt der byteorientierten Klasse PrintStream üblicherweise mit der Konsole verbunden java.io System + static final InputStream in; + static final PrintStream out; + static final PrintStream err;
Einfach Schreiben und Lesen Schreiben nach Standard-out oder -err System.out.print("Hallo Welt!"); System java.io.system out Objekt der Klasse PrintStream print() Methode der Klasse PrintStream read() zum Lesen von Byteströmen mit read(byte[] array) können Bytes von einem InputStream gelesen werden bis entweder der Byte-Array array voll oder der InputStream mit \n beendet ist write() zum Schreiben auf Byteströmen mit write(byte[] array) können Bytes aus dem Byte-Array array auf einen OutputStream geschrieben werden bis der Byte-Array array leer ist Wollen wir nicht eigentlich Zeichen einlesen?
Lesen und Schreiben von Zeichen Klassen Reader und Writer Stream reader allgemein sind Objekte die Byteströme in Zeicheströme umwandeln Stream writer allgemein sind Objekte die Zeicheströme in Byteströme umwandeln sie definieren mehrere read() bzw. write() Methoden mit unterschiedlicher Signatur (für Details siehe Java Documentation) sie werfen IOException wenn I/O-Fehler auftreten das Öffnen von Streams muss durch try - catch geschützt werden Reader Writer read(); write(); close(); close(); StringReader InputStreamReader BufferedReader StringWriter InputStreamWriter BufferedWriter FileReader FileWriter
Konstruktoren für ungepufferte Zeichenströme Reader und Writer sind selbst keine Streams Reader- bzw. Writer-Objekte werden üblicherweise mit einem Input- bzw. OutputStream als Parameter erzeugt Beispiel: InputStreamReader stdin = new InputStreamReader(System.in);
Lesen vom Zeichenstrom mit read() vom Zeichenstrom lesen Rückgabetyp für Zeichen ist int (Unicode) Unicode kann in Character umwandelnt werden cast Beispiel: int zeichenasint; char zeichenaschar = (char)zeichenasint; oder mit Unicodes weiterarbeiten Beispiel: Reading.java
Was man schon immer über Dateien wissen wollte Dateien werden von der Klasse File als Objekt repräsentiert In einem Objekt der Klasse java.io.file werden Dateieigenschaften, (nicht aber der Inhalt!), verwaltet aus einem String (dem vermeindlichen Dateinamen) wird mittels Konstruktor ein Objekt der Klasse File erzeugt Beispiel: File dateiname = new File("myfile.txt");
Lesen von Dateien Anleitung 1. mit dem Dateinamen ein Objekt der Klasse File erzeugen z.b. File datei = new File("in.txt"); 2. ungepufferten Zeichenstrom zum Lesen von der Data erzeugen z.b. Reader in = new FileReader(datei); 3. lesen von in mit read(), zeichenweise 4. gepufferten Zeichenstrom zum Lesen von ungepuffertem Strom erzeugen z.b. Reader inbuffer =new BufferedReader(in); 5. lesen von inbuffer mit readline(), zeilenweise Beispiel: TextKopie.java
BufferedReader und BufferedWriter sind viele Zeichen zu lesen oder zu schreiben ist zeichenweise Verarbeitung uneffektiv Datenpuffer kommen zum Einsatz Pufferung von Daten setzt auf ungepufferten Datenströmen auf BufferedReader(Reader) erzeugt einen gepufferten zeichenbasierten Eingabestrom readline() Rückgabetyp String BufferedReader(Writer) erzeugt einen gepufferten zeichenbasierten Ausgabestrom Beispiel: ReadTextFile.java
Zusammenfassung