Ich hatte gefordert, die Forderung aufgestellt,
dass Exceptions ein Konzept der Programmiersprache sein sollen durch Konzepte,
durch Möglichkeiten der Programmiersprache, unterstützt werden sollen.
Jetzt im nächsten Teil besprechen wir, wie das in Java gemacht wird.
Und dazu sprechen wir über das Java-Sprachkonzept Acception.
Dieses Sprachkonzept erfüllt das, was wir eben postuliert haben.
Es ermöglicht Fehlerreaktionen, je nach Fehlerart, damit vorgefertigt und abgestimmt
und systematisch. Gleichzeitig ist es ein Aspekt der Objektorientierung,
denn Exceptions sind nach Typen in einer Hierarchie geordnet, also eine Acception,
ein Signal, wir sagen gleich mehr dazu, ist ein Exemplar dieser Acception-Klasse.
Selber hat sie einen Typ, lässt sich abfragen und damit
ist es möglich, je nach Fehler eine geeignete Reaktion auszuwählen.
Gleichzeitig durch das zweite Kennzeichen für Objektorientierung neben diesem, oder das dritte,
neben dem Typ ist die Möglichkeit von Generalisierung und Spezialisierung,
ja, wir haben einerseits vordefinierte die Allgemeinen Klassen in Java-Bibliotheken,
sie formen eine Hierarchie,
wo wir Fehlerklassen zusammenfassen und für allgemeine Fehler eine grundsätzliche Reaktion ermöglichen.
Und dann kann man durch Spezialisierung eben Ableitungen,
wie Vererbung in der gleichen Weise hier, Subtypen bilden für eigene Acception-Klassen,
die eine spezielle Reaktion auf Basis der allgemeinen Reaktionen erlauben.
Der Vorteil ist, dass wir die Fehlerreaktionen anpassen können,
mittels dieser Typen und wir können zusätzlich zum Beispiel
zusätzliche Informationen zum Grund oder zusätzliche Informationen für Fehlermeldung,
für die Analyse da hinzufügen und das Ganze wird zur Laufzeit durch die virtuelle Maschine behandelt.
Wir haben hier ein Beispiel auf der nächsten Folie, wie das aussehen kann.
Wir kommen dann gleich noch mal dazu. Ich hoffe,
Sie können das erkennen, dass hier diese vier Klassen
hier oben so leicht grau sind, hinterlegt sind.
Das sind die Klassen, diese Acception-Hierarchie in dem Java-Laufzeit
oder im Java-Bibliotheken mit sich bekommen.
Sroville ist die Oberklasse von allen dieser Klassen in der Acception-Herarchie
und da gibt es zwei Unterklassen-Acception und Error.
Wir sagen gleich noch
was genaueres dazu
Und hier geht es weiter mit Runtime Acception, aber jetzt hier das mit Nichtgrau hinterlegt,
mit weißen Kästen, soll das Beispiel sein, wo wir dann was Eigenes hinzufügen. Mein Beispiel für diese Verallgemeinung,
ja, alle behandelbaren Acceptions sind unter der Klasse Acception hier drin,
alle Ereignisse sind damit zusammengefasst und wir können hier für unsere Anwendung,
was auch immer, vielleicht vom Wasserwerk oder von einer Logistikeinheit irgendwie,
das ist unsere, die Oberklasse der Sachen,
die wir selber schreiben und da sagen wir, okay,
wie zum Beispiel fordern wir, ja, die müssen deklariert werden,
damit wir sie verfolgen können, damit der Programmierer Durchlaufzeitsystem gewandt und sich dem Compiler gewandt, wo seiner was vergessen hat.
Wir kommen gleich noch dazu, die sogenannte Check-Exceptions können wir hier machen.
Ja, und dann können wir noch sagen, okay,
unter diesen Klassen gibt es welche,
die gleich einem Kunden und einem Geschäftsprozess zugeordnet sind,
weil dort Geschäftsträger zum Beispiel geprüft werden und Verletzungen gemeldet werden mittels dieses Acception-Systems.
Ja, und dann, wenn wir auch noch ganz konkrete,
einem konkreten Geschäftsfall einen konkreten Fall haben, zum Beispiel,
dass da eine Rückgabe Termin vergeben wurde,
von der Fafel erletzt worden ist,
können wir auch das hier hinter einem speziellen Typ nehmen,
also von allgemeineren zu immer spezielleren Typen, von Reaktionen.
Ich springe mal zu den Fragen zurück,
das war Folie 4. Ja, hier haben wir die Frage 8.
Wie werden da Objekteorientierte Konzepte angewendet? Und das war jetzt
hier auf der vorgehenden Folie. Ja, einerseits ist das,
haben wir dieses Klassenkonzept für die eigentlichen Ereignisse.
Wir haben den Typen zugeordnet und wir haben diese Hierarchie mit Verallgemeinerung,
Generalisierung und Spezialisierung
Das ist hier möglich. Gut, wir sind jetzt schon zwei weiter. Wir,
diese Systematik der Verallgemeinerung hilft uns dabei,
dass wir unterscheiden können, was ist der Normalfall,
was ist der Ausnahmefall und dann,
dass wir von allgemeineren zu spezielleren Fällen diese Fehlerfälle strukturieren können.
Das kleine Beispiel sollte eben uns helfen,
aber vor allen Dingen wollen wir ja Fehlerreaktionen schon vorbereiten,
sehen, dass sie entsprechend passieren können.
Und diese Fehlerreaktionen entsprechend auch allgemeinere und speziellere zusammenfassen
Soweit erst mal zu dem, wie es prinzipiell passiert.
Und jetzt ganz genau, wie sind, was für Schlüsselworte
bringt Java mit, damit wir damit arbeiten können.
Hier stehen die soweit drauf. Froh ist das Auslösen einer Acception. Turycatch,
Finally, sind Blöcke im Programm, mit die dazuordnen,
wo erwarten wir das, was passiert als Reaktion.
Und manchmal brauchen wir noch einen geordneten Abschluss,
damit wir einen konsistenten Zustand wiederherstellen
Das wäre in dem Final Lied,
wir sagen das gleich alles nochmal im Detail und ros,
auch wenn es sehr ähnlich klingt, wie es wow,
das ist, dass etwas ganz anderes,
da geht es um die Schnittstellendeklaration.
Das ist dann der nächste, der nächste Block.
Zunächst erstmal dieses Twy Catch Finally. Twy leitet einen Block ein,
also wir sehen an den geschweiften Klammern,
so ähnlich wie das für eine Methode gemacht wird,
das ist im Dreiblock wird alles das eingeschlossen,
wo wir erwarten müssen,
dass so
ein Fehlerzustand passiert
Dass ein Fehler durch das Vertragsmodell Verletzungen passiert oder ein Fehler aus der Umgebung passiert.
Hier schließen wir, wir überlegen vorher systematisch,
da kommen wieder Ihre Gedanken hoffentlich zu robusten Programmierstil,
defensiven Programmierstil, ins Frage, dass Sie sich überlegen,
was für Fehler können auftreten und was können wir da Sinnvolles tun.
Das, was auftreten können in diesem Block und im normalen Programmablauf das,
was danach eigentlich käme, wird dann hier unten gemacht,
hier in dem Catchblock, das ist dann separat der Fehlerbehandlungscode.
Ja, der ist dadurch, durch dieses Catch,
ist der getrennt vom übrigen Code.
Ich kann gleich sehen, okay, Catch,
das ist nur das, was ich tue,
im Fall eines Fehlers
Wenn kein Fehler ist, wird er nicht ausgeführt. Finally sind die Anweisungen,
die ich mache, damit ich einen konsistenten Zustand wieder herstelle und
zwar sowohl im Fall des Fehlers als auch im Fall eines Nicht-,
also des ordnungsgemäßen Ablaufs dieser Finally-Block, der kann auch entfallen,
der ist optional in vielen Programmen,
finden Sie die nicht.
Da geht es, würde es also nur gehen.
Der Treiblock und dann geht es weiter zum nächsten,
weiter zum weiteren Programm, was sich hier unten dann entschließt.
Wenn wir ein Finally haben,
dann würde der Treiblock gemacht im Fall des Fehlers,
würde man das Catch,
den Catchbock ausführen und Finally auf jeden Fall
hinterher,
egal ob oder ob nicht
Wie sieht so das, wie sieht da die Reihenfolge aus,
wenn wir so eine Ausnahmebehandlung durchführen?
Zunächst startet das erst mal, wenn wir so eine Ausnahme haben.
Diese Ausnahme ist sowie eine Art Signal zu sehen.
Bing, es ist etwas passiert. Ja,
das passiert dann, wenn die virtuelle Maschine dieses Signal bekommt,
das Signal passiert durch so ein Acception-Ereignis aus dieser Acception-Herarchie.
Dann passiert das Auslösen. Ja,
also dann wird das signalisiert, Achtung,
jetzt muss die Ausnahmebehandlung passieren,
eine Fehlerreaktion soll gestattet werden
Diese aktuell ausgeführte Methode, wo dieser Treiblock drinsteht,
ich bringe mir eine Folie zurück,
also wo das hier drinsteht, der wird abgebrochen.
Und stattdessen wird das Catch, dieser Catchblock ausgeführt, der zu diesem Ereignis gehört.
Und in diesem Ereignis hoffentlich wird diese Kante etwas getan werden,
sinnvoll, um mit diesem Fehler umzugehen, ein Defaultwert nehmen,
den letzten Wert nehmen oder vielleicht auch nur eine Fehlermeldung ausgeben,
wenn man nichts anderes tun kann.
Ja, alles sowas kann passieren,
einschließlich des Aufräumens
Wird so ein Catchblock nicht gefunden im aktuellen Code,
im Umgebung des aktuellen Codes. Dann wird die Methode,
die aktuelle, wo das aufpassiert ist, aufgerufen hat.
Also eins vorher, zu dem wird zurückgekehrt mit dem gleichen Fehlersignal.
Und dort wird dann nach einem Catchblock gesucht, der das
machen kann. Und wenn dort kein Catchblock dafür ist,
dann wieder eins höher, ob dort ein Catchblock ist.
Auf diese Weise kann ich verschiedene Ebenen der Reaktion vorsehen
Ja, also weil sozusagen, es passiert zu einem Weitergeben
, weiter propagieren. Und wir springen die Methoden,
wie sie aufgerufen wurden, sind so langsam zurück.
Sie kennen den Methodenaufrufsdeck, den sie in der Konsole sehen
bei einem Fehler. Diesen Aufrufsdeck springen wir langsam zurück,
bis es irgendwo einen Catch gibt, was diese Operation,
was diese Fehlersituation behandelt. Wenn wir die Main-Methode erreichen,
ohne dass ein Catchblock gefunden wird,
dann war offensichtlich keine Behandlung sinnvoll möglich,
dann müssen wir eben doch
den Abbruch durchführen
Als Entwickler sind wir natürlich versucht oder versuchen wir, unser möglichstes,
dass es dazu nicht kommt, sondern dass irgendwo vorher,
also entweder im eigenen, im eigenen Quellcode,
im eigenen Methode, oder in dem Aufrufer dieser Methode,
dass dort etwas gemacht wird,
dass dort ein Catchblock dafür da ist.
Es gibt die Möglichkeit, mehrere Catchblöcke zu haben,
weil es kann mehrere Fehlerreaktionen es geben.
Kann sein, in einem bestimmten,
bei einer bestimmten Operation greifen sie auf ein Pfeil zu,
was eine Liste enthält
Und da kann es natürlich sein, wir haben, die Liste ist zu Ende.
Es kann sein, wir haben das Pfeil nicht gefunden.
Das sind unterschiedliche Fehlerursachen. Und unterschiedliche Sachen, die ich
da tun kann. Wenn ich nur das Feil nicht gefunden habe,
kann ich vielleicht einfach nochmal versuchen,
einen anderen in Verbindungskanal zu dieser Ressource aufzubauen zum Beispiel.
Wenn ich den, wenn der Index nicht gestimmt hat,
ja, dann ist die Reaktion vielleicht anders möglich.
Welcher ausgeführt wird, ja, das ist nun ein bisschen spezieller.
Also die Reihenfolge ist wichtig, das ist etwas,
was Hypernaus geht. Jeder von ihnen sollte wissen,
es sind mehrere möglich und wir können dann noch überlegen,
welcher das ist, das ist dann das Weiterführende.
Und hier haben wir auch diese Typen und Subtypen,
die dann darauf hält, wo auch Objektorientierung wieder hilft,
mit spezielleren, ich könnte spezielleren Können für Allgemeinere stehen.
Soweit zu diesen Punkten. Und dazu haben wir die Frage
auf Fulle 4, das ist dann die Frage 9,
behandeln von Acceptions mit drei Catch.
Finally, das sollten sie hier erklären können,
lass nämlich zurückspringen ab 50,
Ich bin jetzt hier falsch. 53 geht es los. Ja,
also hier drei Kitch Finally,
das ist, ist hier erklärt auf dieser Folie,
hier haben wir die Anweisung gesehen und hier geht es,
ich sagte es dann, wie, in welcher Reihenfolge,
das passiert.
Nun kommen wir zu dem Punkt, den wir hier zwei
Folien zurück schon hatten, das Erzeugen von Ausnahmen.
Ja, also das hier, wie das hier passiert,
ein zweiter, ach so genau hier,
wo können wir weiterlesen?
Es gibt hier noch
viel mehr
Wie sieht das Auslösen so einer Acception aus?
Natürlich kann zunächst erst mal, das ist das,
was wir gerade besprochen hatten mit Entwicklerfehler und Umgebungsfehler,
ein Ereignis passieren, was irgendwie extern von unserem Code ist.
Ja, also zum Beispiel, was war kein Dateidzugriff möglich,
eine Verbindung hat nicht bestanden, oder es ist einfach etwas Unerwartetes passiert.
Dann wird so ein Acception erzeugt, so ein Acception-Ereignis wird passieren,
dieses Acception-Objekt erzeugt und dieses Object-Acception-Objekt führt wird dann so behandelt,
wie wir es gerade eben gesagt haben.
Das Laufzeitsystem stoppt die aktuelle Behandlung, sucht den Catchblock und so weiter.
Es gibt aber noch eine zweite Möglichkeit und die möchte ich Ihnen anführen.
Und das ist das, wo wir das Schlüsselwort Throw dafür haben.
Wenn der Programmierer annehmen muss, dass irgendetwas Fehlerhaftes passiert,
kann er auch selbst so ein Ereignis provozieren, erzeugen.
Wenn bestimmte Bedingungen nicht erfüllt sind, die er eigentlich erwartet.
Ich möchte jetzt insbesondere auf das Vertragsmodell hinweisen
Ja, der Dienstleister erwartet,
dass der Klient für eine bestimmte Vorbedingung gesorgt hat.
Und wenn die Vorbedingung nicht erfüllt ist, dann kann er nichts machen.
Und dann wäre es zum Beispiel eine gute Idee,
so eine Exception-Objekt zu erzeugen. Und dieses Erzeugen,
als durch den Programmierer, passiert mit dem Schlüsselwort Throw.
Das wird durch die virtuelle Maschine genauso behandelt,
wie wir es eben schon gesagt hatten.
Also stoppen der aktuellen Methode, Catchblock suchen,
den Kitschblock ausführen,
falls wir keinen Catchblock finden,
im Methodenaufruf Kette zurückgehen
Soweit zu dem Throw. Wir haben aber noch einen ganz anderen,
einen sehr ähnlich klingenden Begriff. Und das war,
ich springe mal wieder zu der Folie mit den Fragen,
vor die Nummer 4, erläutern sie,
das Auslösen und Weitergeben von Acception mit Throw und Throws.
Ja, die sind in einer Frage, das ist ein bisschen
eine Falle, weil die Sachen ja sehr unterschiedlich sind.
Wir haben bis jetzt über Throw gesprochen,
ja, mit Throw erzeuge ich,
löse ich so ganz bewusst als Programmierer in einer Zeile,
in einer Anweisung,
löse ich eine Acception aus.
Das war das erste
Ja, jetzt kommen wir zu diesem Weitergeben von Acceptions.
Da kommen wir jetzt bei dem Nächsten, und zwar mit dem Strows.
Das ist das Thema geprüfte und ungeprüfte Acceptions.
Geprüfte Acceptions auf Englisch, Checkt Exceptions, das Prüfen,
wir setzen den Compiler dafür ein, zu prüfen,
dass da auch keine Fehlerbehandlung vergessen wurde.
Ja, das ist eine wunderbare Möglichkeit,
wir brauchen nicht alles nur durch Konventionen machen,
die am Ende durch Disziplin und Aufmerksamkeit nur aufrechterhalten werden.
Nein, wir können den Compiler dafür einsetzen.
Und der Compiler überwacht für uns,
gibt es dort
einen Kitchblock
Und das können wir dadurch einschalten, ganz einfach,
indem wir die deklarieren, dass dort etwas zu passieren hat.
Und das passiert, diese Deklaration passiert mit dem Schlüsselwort Ros.
Im Methodenkopf haben wir das Schlüsselwort Ros,
da steht drin, es wird zu etwas passieren.
Das ist nicht nur das Signal für den Programmierer,
da diese Methode benutzt, sondern auch für den Compiler,
der prüft, ist denn so ein Kitschblock vorhanden.
Der Compiler prüft, ist das vorhanden und das hilft natürlich
sehr.
Es entlastet unsere Aufmerksamkeit
Man setzt das vor allen Dingen da rein,
dafür ein, wo wir Fehler erwarten müssen,
wo wir Fehler vorhersehen müssen, also Umgebungsfehler.
Ja, Server not active acception, IO Acception,
time out acception, das sind jetzt hier Beispiele,
die sie irgendwo im Injava-Bibliotheken verwenden.
Das sind die geprüften Acception mit dem Srows.
Natürlich muss man das nicht machen. Ja, werden fehlen,
es zu machen, weil das doch sehr dafür sorgt,
dass das Programm sehr viel sicherer läuft,
robuster läuft,
Fehler besser vorbereitet ist
Gleichzeitig gibt's noch die ungeprüften Acceptions, die müssen passieren,
nicht mit Deklaration,
dass es nicht, da wird kein Source dazu verwendet,
wir verwenden die dann für Entwicklungsfehler,
da die immer vorkommen können und wir können dort einen Catch oder machen oder auch nicht.
Ja, zum Beispiel hier Beispiel R-Indux out of bounds,
Nypointer, out of memory oder sowas.
Ob geprüft oder nicht, passiert mit dem Compiler.
Zur Laufzeit werden Acceptions immer abgefangen,
da kümmert sich um die virtuelle Maschine dazu,
wir hatten gerade eben
den Ablauf
Ja, also Souls ist hier die Möglichkeit, das zu deklarieren.
Ja, jetzt ein kleiner Ablauf, wie passiert das?
Wir haben eine Methode A, da steht Souls dahinter,
mit Hude B, benutzt Methode A und das geht nur, wenn da ein Ketchburg ist.
Wenn da kein Ketchburg ist, wird es eine Fehlermeldung geben. Ja,
und natürlich gibt es da auch noch die,
wenn kein Ketchburg ist, kann ich die Fehlermeldung nur dadurch vermeiden,
dass ich diese, dass diese Methode B selbst wieder frohes,
das deklariert, ja, ich gebe es weiter.
Damit ist die Freie von der Verpflichtung, das zu machen und das prüft da Compiler.
Entweder mit der Entwickler von Popo-Methode A, gibt diese Verpflichtung vor.
Der Compiler prüft die und wenn der Programmierer von B sagt,
nein, ich kann das nicht beheben, demnächst hören,
dann prüft das bei deinem weitergegebenen,
die dann B aufruft, ob der Compiler das erfüllt hat.
Soweit, zu dem checkt, ancheckt, Beispiele,
wenn wir hier eine Methode haben, Bried Pfeil,
die wirft eine IO-Exception, die soll gecheckt werden,
dann sieht das so aus, ja,
dass wir hier zum Beispiel haben,
Gerd File Content,
Souls IO-Exception
Und wenn ich die dann aufrufe, ja,
also hier haben wir dieses Get-File-Contact, irgendwo,
wo ist es hier, ja, dann wird hier,
gibt es einen 3-Block und den entsprechenden Catch-Block für diese iOcception,
die hier hier so hohes IO-Exception und hier gibt es Catch für diese iOcception und da passiert dann irgendwie hoffentlich etwas Sinnvolles.
Ja, Für diese geprüften und ungeprüften Acceptions gibt es in der Java-Herarchie,
wir haben die grauen Blöcke ja eben schon mal gesehen,
gibt es extra unter Acception die geprüften Acceptions und Runtime-Acceptions sind dann die,
wo wir typischerweise davon ausgehen, dass die nicht behandelt werden können,
aber wir fehlen es trotzdem.
Ja, empfohlen, aber nicht Pflicht. So,
noch ein Beispiel dafür, wie wir selbst etwas deklarieren,
wo etwas wo wir eine, mit Fehlerbehandlungen arbeiten können,
zeige ich mir das mal hier.
Wir haben also eine Range Acception. Ich gehe mal eine Folie
zurück zur 61. Ja, wir sind hier unter Runtime Acception.
Ja, Extens Runtime Acception, das sind also die,
die nicht unbedingt mit hohes, etwas deklarieren müssen.
Wir haben hier einen Lehren, einen parameterlosen Konstruktor,
der diese, das sind hier ganz normal Exemplare von den Klassen.
Deswegen gibt es da auch ganz normalen Konstruktor dafür
Haben wir als im Buddy nur, aufruf des nicht höheren Konstruktors.
Das hätten wir uns eigentlich auch sparen können. Sie erinnern
sich eins letzte Mal, der Standardkonstruktor wird immer aufgerufen.
Hier steht es mehr drin, damit wir es wirklich wissen.
Die nächste Zeile zeigt, ein Konstruktor mit einem Parameter,
der instring ist. Das wird genutzt, um einen Fehlertext wiederzugeben.
Dieser Fehlertext landet im Logfile oder auf der Konsole.
Und was wir hier machen, ist den Konstruktor,
den entsprechenden Konstruktor aufzurufen, der Oberklasse,
nämlich von dem Randheim Acception, der auch diese Fehlertext hat,
der genommen werden kann,
um das genauer anzugeben
Und jetzt eine spezielle, einen neuen Konstruktor,
wo wir eine Zahl übergeben können,
eine ganze Zahl für diesen Index, und zwar,
nein, hierhin, das wollte ich zeigen, Range Acception,
also wir sind außerhalb des Bereichs, ja,
und dann sagen, wie geben wir das,
um hier den Text entsprechend einen vorgefertigten Text zu verwenden,
wo das I dann in der Fehlermeldung drin ist.
Und wir geben das hier entsprechend weiter,
wir nehmen den Superkonstruktor, der mit dem Text hat,
und hier füllen wir gleich den Text mit etwas Sinnvollem.
Soweit zu Fehlern, Wichtig ist, dass wir systematisch das machen können.
Ja, war das Java-Sprachkonzept, Acception, gibt uns die Möglichkeit,
das systematisch zu machen. Und die Unterscheidung,
in was für einer Kategorie für einen Fehler das fällt,
zum Beispiel in Umgebungsfehler oder Entwicklungsfehler, das hilft uns,
die richtige Antwort zu finden.
Dabei denken Sie bitte an das,
was wir in Vorlesung 2 gesagt hatten, zu robusten Verhalten,
zu robusten Systemen, die durch defensiven Programmierstil entstehen.
Soweit vielen Dank, weil es heute so viel war in
der Vorlesung,
ist hier das soweit alles