Praktische Informatik II Problemlöseverfahren Softwareentwurf Dozent: Prof. Thomas Stricker, Ph.D. Unterrichtssprache: Deutsch Programmiersprache: Java Englisches Textbuch: Weiss: Datenstructures and Problem Solving with Java ISBN Eidgenössische Technische Hochschule Zürich Praktische Informatik II 7.5.02 - 1 © Stricker/Mattern Objektorientiertes Programmieren Weltsicht: Die Welt besteht aus verschiedenen interagierenden "Dingen", welche sich klassifizieren lassen. Ding 1 Typ B Ding 2 Typ B Ding 3 Typ A Ding 4 Typ A Ding 5 Typ B Ziel: Betrachteten Weltausschnitt strukturkonsistent mit kommunizierenden Objekten abbilden und modellieren. Simulationssprache SIMULA war die erste objektorientierte Programmiersprache (1967) Objekte: - sind autonome gekapselte Einheiten eines bestimmten Typs - haben einen eigenen Zustand (= lokale Variablen) - besitzen ein Verhalten (wenn sie aktiviert werden) - bieten anderen Objekten Dienstleistungen an - Durchführung von Berechnungen - Änderungen des lokalen Zustandes - Zurückliefern von Variablenwerten oder Berechnungsergebnissen - Allgemein: "Reaktion" auf Aufruf einer Methode 102 Praktische Informatik II 7.5.02 - 2 © Stricker/Mattern Objektorientierter Softwareentwurf - Strukturierung der Problemlösung in eine Menge kooperierender Objekte - Entwurf der Objekttypen, dabei ähnliche Objekte zu Klassen zusammenfassen - Herausfaktorisierung gemeinsamer Aspekte verschiedener Klassen ==> Hierarchie festlegen, Klassenbibliothek - Festlegung einzelner Dienstleistungen (--> Methoden) - Entwurf der Objektbeziehungen ("Protokoll") - Feinplanung der einzelnen Methoden, Festlegung der Klassenattribute etc. - Strukturierung und Implementierung der Methoden (klassisches Programmieren im Kleinen) 103 Praktische Informatik II 7.5.02 - 3 © Stricker/Mattern Objektorientiertes Modellieren - Es sollte bereits in frühen Phasen des Softwareentwurfs (Problemanalyse, Anforderungsdefinition) das Objektparadigma verwendet werden - Leitlinie: Betrachteten Ausschnitt der Welt "strukturkonsistent" mittels interagierende Objekte abbilden - Problem: Geeignete Objekte und Typen im Anwendungsbereich identifizieren - Aufgabe: Relevante Merkmale der Objekte identifizieren - Aufgabe: Interaktionsmuster der Objekte analysieren (Informationsfluss; Geflecht von Dienstleistungen) Das objektorientierte Modellieren als Prinzip ist in mancherlei Hinsicht eher eine "Kunst" als eine Technik - eine eindeutige Methode gibt es nicht - es wird eine Vielzahl von methodischen Ansätzen gehandelt, die z.T. durch Werkzeuge und Techniken (oft "halbformaler" Art, z.B. strukturierte graphische Diagramme) unterstützt werden Praktische Informatik II 7.5.02 - 4 © Stricker/Mattern Vererbung ("inheritance") Mensch Spezialisierung Verallgemeinerung Geschäftsmann Kaufmann Sportler Rennfahrer Internetprovider Student Sportstudent Bäcker Informatikstudent Taxonomie in Form eines Konzeptverbandes - Spezialisierung, Verallgemeinerung - ein Informatikstudent ist ein Mensch mit Programmierkenntnissen - ein Rennfahrer ist ein spezieller Sportler - Alle Merkmale, Eigenschaften... des umfassenderen Begriffs werden auf den Unterbegriff vererbt - ein Rennfahrer hat mehr Eigenschaften als ein (beliebiger!) Sportler - ein Rennfahrer erbt von zwei Oberkonzepten (Mehrfachvererbung ) - Bem.: Mehrfachvererbung ("multiple inheritance") in Java nicht möglich - Vererbungsrelation ist transitiv - ein Bäcker hat alle Eigenschaften eines ("generischen") Menschen - Ein Objekt (als "Begriffsinstanz") hat viele Facetten - ein Rennfahrer kann je nach Zweckmässigkeit auch entweder nur als Sportler oder als Geschäftsmann oder schlicht einfach als Mensch betrachtet werden 105 Praktische Informatik II 7.5.02 - 5 © Stricker/Mattern Klassenhierarchie als Konzeptbaum Konzeptbaum: Basisklasse (auch: “Oberklasse”) Fahrzeug Fahrrad Auto Personenwagen VW abgeleitete Klassen von "Fahrzeug" (auch: “Unterklassen” oder “erweiterte Klassen”) Lastwagen Ford Entwurf eines Klassenbaumes ist wichtige Aufgabe der Entwurfsphase beim objektorientierten Programmieren! "is-a"-Relation - Ein VW ist ein Personenwagen ist ein Auto ist ein Fahrzeug - Eine Trompete ist ein Blasinstrument ist ein Musikinstrument - Ein Fahrzeug hat Räder ==> ein Personenwagen hat Räder Praktische Informatik II 7.5.02 - 6 © Stricker/Mattern Abgeleitete Klassen, Redefinition - Eine abgeleitete Klasse besitzt automatisch alle Eigenschaften der zugehörigen Basisklasse(n). - Konkret: Sie besitzt alle Attribute und alle Methoden der Basisklassen. - Ausser: Es werden einige davon unsichtbar gemacht oder einige Methoden redefiniert. heissen noch genauso, tun aber etwas anderes! - Eine abgeleitete Klasse kann zusätzliche Attribute und Methoden definieren. Fahrzeug: - Radzahl - km-Stand "Fahrzeugteil" eines Autos Auto: Personenwagen: - Radzahl - km-Stand - PS - Hubraum "Autoteil" eines Personenwagens - Radzahl - km-Stand - PS - Hubraum - Beifahrerzahl - Eine Methode "Berechne_Steuer" lässt sich nicht für alle Fahrzeuge gleichermassen definieren. ==> Man würde z.B. in "Auto" eine Standardmethode vorsehen (Benutzung von "Hubraum"), jedoch für spezielle Fahrzeuge (z.B. Elektroautos) diese Methode anders definieren. Praktische Informatik II 7.5.02 - 7 107 © Stricker/Mattern Ein Beispiel in Java Vorfahre weiss nicht von den Erben; Er- class Fahrzeug be muss sich seinen Vorfahren aussuchen! { public int Radzahl;}; class Auto extends Fahrzeug { public int PS; public float Hubraum;}; Erweiterung der Klasse "Fahrzeug": Alles, was in "Fahrzeug" deklariert ist, gehört damit auch zu "Auto" (sowohl Attribute als auch Methoden) - mit gewissen Einschränkungen (--> später) class PW extends Auto { public int Beifahrerzahl; void print() {System.out.println("Radzahl: "+ Radzahl + Beifahrerzahl: " + Beifahrerzahl);} }; class LW extends Auto { public float Zuladung; }; Auf "weiter oben" definierte Attribute kann ohne weiteres zugegriffen werden diese sind Teil der abgeleiteten Klasse! class Beispiel { public static void main (String args[]) { Fahrzeug f = new Fahrzeug(); Auto a = new Auto(); Hier werden Instanzen (also PW p = new PW(); Objekte) der verschiedensten LW l = new LW(); Hierarchiestufe erzeugt. p.Beifahrerzahl = 5; p.PS = 70; p.Hubraum = 1794; p.Radzahl = 4; p.print(); p.Zuladung geht natürlich nicht! Zugriff auf Variablen und Methoden des mit ’p’ bezeichneten PW-Objektes. Idee: Gemeinsame Aspekte herausfaktorisieren und in eine übergeordnete Klasse einbringen. 108 Praktische Informatik II 7.5.02 - 8 © Stricker/Mattern Zuweisungskompatibilität - Objekte von abgeleiteten Klassen können an Variablen vom Typ der Basisklasse zugewiesen werden. - Fahrzeug f; Auto a; ... f = a; - Variable f kann Fahrzeugobjekte speichern. - Ein Auto ist ein Fahrzeug. - Daher kann f auch Autoobjekte speichern. - Die Umkehrung gilt jedoch nicht! - a = f; ist verboten! - Variable a kann Autoobjekte speichern. - Ein Fahrzeug ist aber kein Auto! "Gleichnis" zur Zuweisungskompatibilität: Auf einem Parkplatz für Fahrzeuge dürfen Autos, Personenwagen, Fahrräder... abgestellt werden. Auf einem Parkplatz für Fahrräder jedoch keine beliebigen Fahrzeuge! - Merke also: Eine Variable vom Typ "Basisklasse" darf ! auch ein Objekt der abgeleiteten Klasse enthalten! Man nennt diese Eigenschaft auch Polymorphismus, da eine Referenz auf Objekte verschiedenen Typs zeigen kann (bzw. eine Variable Werte untersch. Typs haben kann). Beispiel: Eine Variable vom Typ "Referenz auf Fahrzeug" kann zur Laufzeit sowohl zeitweise auf PW-Objekte, als auch zeitweise auf LW-Objekte zeigen. Praktische Informatik II 7.5.02 - 9 109 © Stricker/Mattern Ein Java-Beispiel class Fahrzeug {... int Radzahl;} class Auto extends Fahrzeug {...float Hubraum;} class PW extends Auto ... Fahrzeug Fahrzeug f; Auto a; PW p; Radzahl ... new ... p.Hubraum = 1702; Ein PW ist ein Auto Auto und ein Fahrzeug p.Radzahl = 4; Hubraum a = p; f = p; Eine Fahrzeug-Variable darf PWObjekte und Auto-Objekte speichern f = a; PW /* a = f; */ /* incompatible types for =... */ Andersherum geht es nicht! a.Radzahl = 3; a.Hubraum = 1100; Es wurde zwar Radzahl und Hubf = a; raum zugewiesen; auf Hubraum System.out.println ist aber über f nicht zugreifbar! (f.Radzahl); /* System.out.println(f.Hubraum); */; /* No variable Hubraum defined in Fahrzeug */ - f.Hubraum ist aus gutem Grund verboten: Auf f könnte ja zufällig ein Fahrrad (ohne Hubraum!) "parken"! - durch Umtypen kommt man aber notfalls auch über f an den Hubraum des Auto-Objektes: System.out.println(((Auto)f).Hubraum); - aber wenn dort "gerade" kein Auto (sondern ein Fahrrad) parkt? Dann gibt es einen Laufzeitfehler "ClassCastException"! - dem kann man wie folgt vorbeugen: if (f instanceof Auto) System.out.println(((Auto)f).Hubraum); else System.out.println("kein Auto, kein Hubraum!"); 110 Praktische Informatik II 7.5.02 - 10 © Stricker/Mattern Polymorphie und abstrakte Methoden - Polymorphie = "Vielgestaltigkeit" - eine Variable kann Werte unterschiedlichen Typs annehmen - bzw.: eine Referenz kann auf Objekte unterschiedlichen (aber "verwandten") Typs verweisen - Objekte unterschiedlichen Typs haben gleichnamige Methoden Beispiel: Methode "Flächenwert" ist für alle Objekttypen realisiert, jedoch unterschiedlich je nach Typ! Geometrisches Objekt Ellipse Rechteck Kreis Quadrat Dreieck - Polymorphe Liste: Anker next abstract class geo_ob { geo_ob next; public abstract double flaechenwert();}; Diese Methode für jede abgeleitete Klasse mit sinnvoller Semantik versehen! - Eine Klasse mit abstrakten Methoden muss selbst als "abstract" deklariert werden - Abstrakte Methoden werden von den abgeleiteten Klassen jeweils spezifisch implementiert Praktische Informatik II 7.5.02 - 11 111 © Stricker/Mattern Polymorphe Liste class Dreieck extends geo_ob { /* Koordinaten etc. als Attribute */ { public double flaechenwert() ... /* bekannte Formel anwenden */ System.out.print("Dreiecksfläche:...”);} } } class Kreis extends geo_ob /* ähnlich */ - Eine polymorphe Liste kann man dann z.B. so durchlaufen: for (geo_ob z = Anker; z != null; z = z.next) F = F + z.flaechenwert(); Alle Flächenwerte aufaddieren - Die Verabeitung der einzelnen Objekte kann unabhängig von ihrem eigentlichen Typ geschehen. - In der Praxis wird eine solche "Verabeitung" i.a. wesentlich komplexer sein als hier angedeutet. - Es können ohne den Verabeitungsalgorithmus anzupassen neue Objekttypen als Unterklassen von "geo_ob" eingeführt werden (z.B. ’Quadrat’). Nur hinzufügen, aber nichts verändern (im Idealfall) vermindert den Wartungsaufwand beträchtlich! - Late binding: Es wird zur Laufzeit berechnet, welche Methode "angesprungen" wird; dies steht zur Übersetzungszeit (--> "early binding") noch nicht fest! 112 Praktische Informatik II 7.5.02 - 12 © Stricker/Mattern Generische Methoden und abstrakte Klassen abstract class Sort { abstract boolean kleiner (Sort y); static void sort(Sort[] Tab) { for (int i=0; i<Tab.length; i++) for (int j=i+1; j<Tab.length; j++) if (Tab[i].kleiner(Tab[j])) { Sort swap = Tab[i]; Tab[i] = Tab[j]; Achtung: Es wird Tab[j] = swap; absteigend sortiert! } } } Das einfache Sortierverfahren ("deletion sort") ist ineffizient! - Wir fordern, dass die zu sortierenden Objekte vom Typ einer von Sort abgeleiteten Klasse sind. - In der abgeleiteten Klasse muss ausserdem die Methode "kleiner" realisiert werden. Als totale Ordnungsrelation auf den Objekten! - Unabhängig davon, wie die Relation "kleiner" definiert ist, funktioniert unser Sortierverfahren! - Das Sortierverfahren kann also bereits implementiert (und getestet) werde, bevor überhaupt die Daten selbst bekannt sind! - Einmal entwickelt, kann man den Algorithmus auch zum Sortieren anderer Datentypen verwenden! (int, float, Brüche als rationale Zahlen, Zeichenketten...) - Sort ist eine abstrakte Klasse (von solchen können keine Objekte erzeugt werden, sie dienen nur dazu, hiervon abgeleitete Klassen zu definieren). 113 Praktische Informatik II 7.5.02 - 13 © Stricker/Mattern Anwendung des Sortierverfahrens - Es sollen einfache int-Werte sortiert werden, und zwar unter Benutzung der existierenden generischen Sortierroutine (ohne diese kennen zu müssen!): class Int_Sort extends Sort { int w; Dies ist die vom Anwender bereitgestellte Klasse (der Basisklasse Sort) Int_Sort(int i) {w = i;} Konstruktor boolean kleiner (Sort y) { return w < ((Int_Sort)y).w; } } Hier wird die Relation "kleiner" definiert und implementiert class ... Diese Klasse verwendet beispielhaft Int_Sort ... Int_Sort[] Tabelle = new Int_Sort[12]; for (int i=0; i<Tabelle.length; i++) { Tabelle[i] = Füllen mit Zufallszahlen new Int_Sort((int)(Math.random()*20.0)); System.out.print(" " + Tabelle[i].w); } Name einer Klasse, nicht einer Referenz! Referenzübergabe! Int_Sort.sort(Tabelle); System.out.println(); for (int i=0; i<Tabelle.length; i++) System.out.print(" " + Tabelle[i].w); System.out.println(); ... 114 Praktische Informatik II 7.5.02 - 14 © Stricker/Mattern Eine andere Sortieranwendung class Studi extends Sort { int Semester; String Name, Fach; Studi(int S, String F, String N) Konstruktor {Semester = S; Name = N; Fach = F;} Hier darf leider nicht Studi stehen boolean kleiner (Sort y){ Typkonversion von Studi s = (Studi) y; return ((Semester < s.Semester) Sort nach Studi! || ((Semester == s.Semester) && (Fach.compareTo(s.Fach)<0)) || ((Semester == s.Semester) && (Fach.compareTo(s.Fach)==0) && (Name.compareTo(s.Name)<0))); } Es wird in erster Linie nach Semesterzahl (absteigend) } sortiert, nur bei Gleichheit nach Fach bzw. Name class ... ... Studi[] Tab = new Studi[8]; Tab[0] = new Studi(10,"Bio","Hase"); Tab[1] = new Studi(8,"Mathe","Oberzahl"); ... Statt dessen würde man in der Praxis die Daten von einer Datei einlesen Tab[7] = new Studi(6,"Physik","Kraft"); Studi, von Sort abgeleitet, kennt auch die Methode sort Studi.sort(Tab); Es wird ein array vom Typ Sort erwartet, aber ein array vom Typ Studi übergeben for (int i=0; i<Tab.length; i++) System.out.println(Tab[i].Name + " " + Tab[i].Fach + " " + Tab[i].Semester); ... 115 Praktische Informatik II 7.5.02 - 15 © Stricker/Mattern Das Sortierergebnis 10 Bio Hase 8 Mathe Oberzahl 8 Mathe Viereck 2 Geologie Steinbeisser 4 Bio Bluemlein 6 E-Technik Strom 10 Mathe Rechenberg 6 Physik Kraft Rechenberg Mathe 10 Hase Bio 10 Viereck Mathe 8 Oberzahl Mathe 8 Kraft Physik 6 Strom E-Technik 6 Bluemlein Bio 4 Steinbeisser Geologie 2 Die Eingabedaten Das Sortierergebnis (absteigend sortiert entsprechend dem festgelegten Sortierkriterium "SemesterFach-Name") - Um eigene Datentypen sortieren zu können, muss die entsprechende Klasse also nur als abgeleitete Klasse von "Sort" deklariert werden. - Ferner muss dort die "kleiner-Operation" geeignet festgelegt werden. Praktische Informatik II 7.5.02 - 16 116 © Stricker/Mattern Sortieren geometrischer Objekte - Wir sortieren Quadrate und Kreise nach ihrer Fläche - die Fläche wird jeweils typspezifisch berechnet abstrakte Klassen Sort kleiner geo_ob kleiner flaeche Quadrat Kreis laenge radius flaeche abstrakt abstract class geo_ob extends Sort { public abstract double flaeche(); boolean kleiner (Sort y) { geo_ob x = (geo_ob)y; return flaeche() < x.flaeche();} } class Quadrat extends geo_ob { double laenge; public double flaeche() { return (laenge*laenge); }; Quadrat() { laenge = kbdInput.readInt("Laenge? ");} } Konstruktor class Kreis extends geo_ob { double radius; public double flaeche() { return (3.14159*radius*radius); }; Kreis() { radius = kbdInput.readInt("Radius? ");} } Konstruktor 117 Praktische Informatik II 7.5.02 - 17 © Stricker/Mattern Das zugehörige Testprogramm public static void main(String[] args) { geo_ob[] Tabelle = new geo_ob[3]; for (int i=0; i<Tabelle.length; i++) { String s = kbdInput.readString ("Kreis (k) oder Quadrat (q) ? "); if (s.compareTo("k") == 0) Polymorphie Tabelle[i] = new Kreis(); else Tabelle[i] = new Quadrat(); } geo_ob.sort(Tabelle); System.out.println(); for (int i=0; i<Tabelle.length; i++) System.out.print(" " + Tabelle[i].flaeche() ); System.out.println(); } Hier wird jeweils die "richtige" Methode für die Fläche verwendet Kreis (k) oder Quadrat (q) ? k Radius? 5 Kreis (k) oder Quadrat (q) ? q Laenge? 3 Kreis (k) oder Quadrat (q) ? q Laenge? 7 78.5397 49 9 118 Praktische Informatik II 7.5.02 - 18 © Stricker/Mattern Java: Mehrfachvererbung? - Zweck: "mix in"; Verheiraten mehrerer Konzepte - Beispiel: geometrische Formen geometrisches verschiebe() Objekt fläche() umfang() färbe() gefülltes Objekt Quadrat versende() empfange() über Internet verschickbar gefülltes Quadrat - "gefülltes" Quadrat soll Methoden und Attribute von mehreren Klassen erben können - keine Baumstruktur, sondern gerichteter Graph! - Probleme: - gleich benannte Attribute in verschiedenen Vorgängerklassen: welches davon wird geerbt? - oft nicht zu vermeiden, da Vorgängerklassen von verschiedenen Entwicklern realisiert wurden - daher Mechanismen zur "Konfliktauflösung" notwendig (z.B. beim Erben umbenennen; Angabe, welche man erben möchte; Sprachregeln, die festlegen, was im Konfliktfall Vorrang hat etc.) - Mehrfachvererbung z.B. möglich in C++, aber nicht in Java - um Sprache (und Implementierung) einfach zu halten - als teilweisen Ersatz dafür dienen in Java die "Interfaces" 119 Praktische Informatik II 7.5.02 - 19 © Stricker/Mattern Schnittstellen ("Interfaces") - Interface = (abstrakte) Klasse, die alle Methoden nur deklariert, aber nicht implementiert - enthält also nur (implizit) abstrakte Methoden (und Konstanten) - Bsp: interface Menge { int cardinal(); void insert (Object x); statt void remove (Object x); "class" } Oberklasse aller Objekte - alle "Variablen" sind automatisch public static final (also Konstanten) - alle Methoden sind automatisch public abstract - Interface muss von anderen Klassen implementiert werden - Bsp: class S implements Menge { ... public int cardinal(); { ... while ... i++ ... return i; } - implements hat die gleiche Rolle wie extends bei "echten" Klassen - es kann auch eine entsprechende Hierarchie entstehen - Der Typ des Interfaces (hier: "Menge") kann mit seinen Methoden anderswo benutzt werden - Bsp: Menge M; M.insert(...); 120 Praktische Informatik II 7.5.02 - 20 © Stricker/Mattern Mehrfacherweiterungen - Interfaces können mehrere andere erweitern - Bsp: interface A {...} interface B {...} interface I extends A, B {...} int X(); } - I "enthält" alle Methoden von A und B (und zusätzlich X) - eine Klasse dagegen kann nur eine einzige Klasse erweitern (aber gleichzeitig mehrere Interfaces implementieren): class P extends Q implements A,B,... {...} - Das sogen. "diamond inheritance problem" ist so entschärft: W X Y interface W {...} interface X extends W {...} class Y implements W {...} class Z extends Y implements X {...} Z - die von Z ererbten Attribute und Methodenimplementierungen können nur aus Y (und nicht indirekt doppelt aus W stammen) 121 Praktische Informatik II 7.5.02 - 21 © Stricker/Mattern Schnittstellen ("Interfaces") - Interface = (abstrakte) Klasse, die alle Methoden nur deklariert, aber nicht implementiert - enthält also nur (implizit) abstrakte Methoden (und Konstanten) - Bsp: interface Menge { int cardinal(); void insert (Object x); statt void remove (Object x); "class" } Oberklasse aller Objekte - alle "Variablen" sind automatisch public static final (also Konstanten) - alle Methoden sind automatisch public abstract - Interface muss von anderen Klassen implementiert werden - Bsp: class S implements Menge { ... public int cardinal(); { ... while ... i++ ... return i; } - implements hat die gleiche Rolle wie extends bei "echten" Klassen - es kann auch eine entsprechende Hierarchie entstehen - Der Typ des Interfaces (hier: "Menge") kann mit seinen Methoden anderswo benutzt werden - Bsp: Menge M; M.insert(...); 120 Praktische Informatik II 7.5.02 - 22 © Stricker/Mattern Ausnahmen (Exceptions) - Ausnahmen sind Fehlerereignisse - werden oft vom System ausgelöst ("throw") - können aber auch explizit im Programm ausgelöst werden - können abgefangen und behandelt werden ("catch") - Bessere Strukturierung durch "try" und "catch": readFile() { try { // open the file; // determine its size; // allocate that much memory; // read the file into memory; // close the file; } catch (fileOpenFailed) { // doSomething; } catch (sizeDeterminationFailed) { // doSomething; } catch (memoryAllocationFailed) { // doSomething; } catch (readFailed) { // doSomething; } catch (fileCloseFailed) { // doSomething; } } - Fehlerbehandlung muss auf diese Weise nicht mit dem "normalen" Programmcode verwoben werden Praktische Informatik II 7.5.02 - 23 © Stricker/Mattern Ausnahmen - ein E/A-Beispiel import java.io.*; Da wir Fehler selbst public class EA_Beispiel abfangen, können // Prints "Hello World" to a file wir auf "throws..." // specified by the first parameter. verzichten! { public static void main(String args[]) { FileOutputStream out = null; // Attempt to open the file, if we // can't display error and quit try { out = new FileOutputStream(args[0]); } Diese Fehlerklasse ganz oben in der Hierarchie und catch (Throwable e) fängt damit alles ab { System.out.println("Error in opening file"); System.exit(1); } Z.B.: Zugriffsrechte "falsch" PrintStream ps = new PrintStream(out); try { } Fehler hierbei würden nicht abgefangen! ps.println("Hello World"); out.close(); Über diese Variable kann man } catch(IOException e) mehr über den Fehler erfahren { System.out.println("I/O Error"); System.exit(1); } } Shortcut zum Verlassen des Programms Praktische Informatik II 7.5.02 - 24 © Stricker/Mattern Fehlerarten - Typische Situationen, in denen Ausnahmen auftreten können: - Ein- / Ausgabe (IOException) - Netz (z.B. MalformedURLException) - Erzeugen von Objekten mit "new" - Typkonvertierung (z.B. NumberFormatException) - Wichtige Fehlerklasse: Laufzeitfehler - können, müssen aber nicht abgefangen werden - Beispiele: Zugriff über Null-Referenz; int / 0; Indexfehler bei arrays try { value = value / x; } catch(ArithmeticException e){ System.out.println("Division durch 0?"); } - Alle anderen Fehlerarten müssen behandelt werden - entweder durch try / catch in der Methode - oder durch Angabe, dass die Methode diese Ausnahme selbst wieder auslöst (und damit weiterreicht), z.B.: import java.io.*; public Eine_Methode (...) throws java.io.IOException {... read ...} Praktische Informatik II 7.5.02 - 25 © Stricker/Mattern Praktische Informatik II 7.5.02 - 26 © Stricker/Mattern Praktische Informatik II 7.5.02 - 27 © Stricker/Mattern Praktische Informatik II 7.5.02 - 28 © Stricker/Mattern