Unsere Datenschutzrichtlinie wird in Kürze aktualisiert. Bitte sehen Sie sich die Vorschau an.

Java 7 Grundkurs

finally, try-with-resources

Testen Sie unsere 2016 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
Manche Anweisungen sollen unbedingt ausgeführt werden, unabhängig davon, ob vorher ein Problem aufgetreten ist oder nicht. Und wenn externe Ressourcen geöffnet wurden, wie Dateien oder Netzwerkverbindungen, sollten diese nach ihrer Verwendung auch wieder geschlossen werden. Für beide Anforderungen gibt es in diesem Video die passenden Lösungen.
08:28

Transkript

In diesem Video lernen Sie das Schlüsselwort "finally" kennen, und Sie erfahren, wie automatische Ressourcenverwaltung funktioniert. Ich habe dazu dieses kleine Beispielprojekt vorbereitet, es enthält eine Klasse mit einer "Main-Methode". Ich zeige Ihnen zuerst mal, was das Programm eigentlich tut, und dazu führe ich es aus. Ich kann hier eine Zahl eingeben, muss ich unten reinklicken, "Enter". Jetzt gebe ich noch eine Zahl ein, "Enter", und dann steht da "Die Summe von 6 und 5 ist 11". Unglaublich! Schauen wir uns kurz an, wie das Programm funktioniert. Ich verwende hier die Klasse "Scanner" aus dem Paket "java.util", um aus der Standardeingabe zu lesen. Die Standardeingabe, das ist standardmäßig die Tastatur. "Scanner" liest aus dem hereinkommenden Datenstrom, in unserem Fall von der Tastatur, und wandelt das, was da reinkommt, gleich in die gewünschten Datentypen um. Ich zeige Ihnen diese Klasse mal kurz in der "java.doc". Hier haben wir die Klasse "Scanner", Package "java.util". Und nun gibt es hier für jeden Datentyp, den ich gern haben möchte, die passende Methode. Die Interpretierung und Umwandlung übernimmt, wie gesagt, "Scanner". Ich habe hier Methoden, die heißen z.B. "nextLong", dann bekomme ich also das, was als nächstes reinkommt, einfach als "Long" übersetzt. Mit "nextLine" kann ich die ganze nächste Zeile bekommen und zwar als String. Und so geht das durch alle anderen Datentypen durch. "nextDouble" liefert ein "double", "nextBoolean" ein "boolean" usw. Zurück zu unserem kleinen Programm: Nachdem wir den Scanner erzeugt haben und ihn "In" genannt haben, weil wir wollen Daten reinholen, kommt die kurze Textmeldung "Gib eine ganze Zahl ein", und dann nehmen wir diesen Scanner und rufen "nextInt" auf. D.h. was jetzt eingegeben wird, wird in eine "Int" umgewandelt, und dann der Variablen "A" zugewiesen. Das Ganze wiederholt sich dann nochmal, diesmal in die Variable "B". Schließlich wird die Programmausgabe zusammengestellt, die Sie ja gerade gesehen haben, und dann ist das Programm auch schon wieder zu Ende. Dieses ausgefuchste Programm hat allerdings einen Fehler. Unser Scanner-Objekt belegt nämlich, neben dem Stück Speicher für das eigentliche Objekt, noch weitere Ressourcen, und diese Ressourcen müssen auch explizit wieder freigegeben werden. In der Klasse "Scanner" gibt es dafür die Methode "close". Rufe ich diese Methode nicht auf, dann bleiben die Ressourcen belegt, solange das Programm läuft. Bei länger laufenden Programmen, kann das dann irgendwann zu Ressourcenengpässen führen. Deswegen ist es immer eine gute Idee, solche Objekte, die mit externen Ressourcen arbeiten, auch wieder sauber freizugeben, sobald man sie nicht mehr benötigt. Kein Problem, dann schreiben wir einfach ein "in.close" hier drunter, und alles scheint gut zu sein. Nicht ganz, natürlich, und das zeige ich Ihnen bei einem erneuten Programmlauf. Ich führe das Programm nochmal aus. Jetzt soll ich hier eine Zahl eingeben. Ich gebe aber etwas anderes als eine Zahl ein. Wenn ich jetzt "Enter" drücke, dann versucht der Scanner das in eine Zahl umzuwandeln, und das funktioniert nicht, und deshalb wirft der Scanner jetzt eine "InputMismatchException" aus. Da in so einem Programm von einem "try" oder gar von einem "catch" weit und breit nichts zu sehen ist, wird diese "exception", die hier in dieser Zeile auftritt, auch nirgendwo behandelt. Die Abarbeitung dieser Methode wird also an dieser Stelle beendet. In unserem Fall ist das jetzt zwar die "Main-Methode", aber in einem größeren Programm kann es natürlich auch eine beliebige andere Methode sein. Der Punkt um den es hier geht: "close" wird nicht mehr aufgerufen, denn die Methode wird ja vorher schon verlassen. Ich möchte hier noch nicht die auftretende "exception" behandeln, ich möchte wirklich erst mal nur dafür sorgen, dass der Scanner geschlossen wird, bevor wir die Methode verlassen. Hierfür gibt es ein eigenes Schlüsselwort und das heißt "finally". "finally" funktioniert aber nur in Verbindung mit einem "try" davor. Die ganze Sache sieht also jetzt folgendermaßen aus: Wir fügen diesen Bereich hier in einen "try-Block" ein, und dann das hier unten in ein "finally". Ich mache das mal. Also hier ein "try" davor, und hier jetzt kein "catch", sondern gleich ein "finally". Jetzt haben wir gleich ein Problem. Sie sehen das schon an den roten Kringeln. Aber erst mal rücke ich noch vernünftig ein. Rechte Maustaste, "Format", und jetzt sehen wir vielleicht auch schon, was das Problem ist. Wir möchten hier unten auf die Variable "in" zugreifen. "in" wird aber hier oben im "try"-Block deklariert. Eine Variable ist immer in dem Block gültig, in dem sie deklariert wird. D.h. also, die Gültigkeit von "in" endet hier an dieser geschweiften Klammer zu. Damit wir auch im "finally"-Block auf "in" zugreifen können, müssen wir also die Deklaration eine Ebene höher schieben, D.h. diese Deklaration nehme ich hier raus und setze sie vor den "try"-Block und hier ein "in" hin. Jetzt ist der Compiler aber immer noch nicht glücklich. Jetzt sagt er mir nämlich: "Die Variable ist möglicherweise nicht initialisiert worden." Klar, ist ja ein "try"-Block und der könnte ja vorzeitig abgebrochen werden. Sogar so vorzeitig, dass "in" noch nicht mal eine gültige Referenz auf einen Scanner bekommt. Eine Initialisierung ist aber schnell gemacht, denn auch eine Initialisierung mit "Null" ist für den Compiler eine gültige Initialisierung. Aber wenn "in" "Null" ist und wir tatsächlich hier die Initialisierung nicht erreichen sollten, warum auch immer, dann würde hier der Methodenaufruf ins Leere greifen, das Programm würde wieder abbrechen. Also müssen wir noch einen Test drumherum bauen: "if", "in", ≠, "Null". Dann noch hier das "close". Jetzt ist alles, wie es sein sollte. Sieht zwar etwas komplizierter aus, aber das Ressourcenleck ist erst mal geschlossen. Die Ausführung beginnt hier, "in" wird deklariert und auf "Null" gesetzt. Dann betreten wir den "try"-Block. Wann auch immer wir ihn verlassen, ob wir ihn normal verlassen, indem wir die letzte Zeile erreicht und ausgeführt haben, oder ob wir ihn vorzeitig verlassen, weil irgendeine "exception" auftritt, in jedem Fall wird nach Verlassen dieses "try"-Blocks der "finally"-Block ausgeführt. Also normale Abarbeitung heißt: Scanner erzeugen, Zahlen einlesen, Ergebnis ausgeben, Scanner schließen. Und der problematische, der mit "exception", Ablauf heißt dann: Scanner erzeugen, Zahl versuchen einzulesen, abbrechen, aber bevor wir raus gehen aus dieser Methode, noch "finally" ausführen, also Scanner schließen. Einen solchen "finally"-Block kann ich also wunderbar verwenden, um notwendige Aufräumarbeiten durchzuführen, die auf jeden Fall passieren sollen. Sie können hier z.B. auch noch Statusmeldungen ausgeben, Datenbankverbindungen schließen, was auch immer getan werden muss. Wir wollen hier allerdings nichts von alledem. Wir wollen keine Statusmeldungen ausgeben, wir wollen nichts anderes schließen als diesen Scanner, den wir oben erzeugt haben. Und hierfür gibt es jetzt einen Mechanismus, der heißt "automatische Ressourcenverwaltung". Und das funktioniert so: Zu Beginn meines "trys", noch vor der geschweiften Klammer auf, deklariere ich die Ressourcen, die ich innerhalb meines "try"-Blocks benötige. Die Ablaufumgebung kümmert sich dann darum, dass all diese Ressourcen, die ich dort deklariert habe, das können auch mehrere sein, dass also all diese Ressourcen geschlossen werden, wenn ich den "try"-Block wieder verlasse, und zwar egal, wie ich ihn verlasse, ob ich ihn normal verlasse oder durch eine "exception", ist völlig egal. Für mich heißt das, ich spare mir hier unten diesen "finally"-Block. Wohlgemerkt, "finally" ist damit nicht völlig überflüssig, nur eben für solche Fälle, wo ich einfach nur eine Ressource schließen möchte, da brauche ich es nicht mehr. Da die zu verwendenden Ressourcen direkt hinter dem "try" deklariert werden, wird das Ganze auch als "try with ressources" bezeichnet. Und das ist es auch, was mir NetBeans hier die ganze Zeit zu sagen versucht, nämlich, dass ich das Ganze ja in ein "try with ressources" konvertieren könnte. Da steht es. Klicke ich mal drauf. Sage ich "Ja" indem ich hier draufklicke und es wird konvertiert. Wir sehen schon, es ist alles ein Stückchen kürzer geworden. Der "finally"-Block ist verschwunden, und die separate Deklaration der Scanner- Variablen oben ist auch verschwunden. Brauchen wir ja nicht mehr. Die Syntax ist recht unkompliziert. Nach dem Schlüsselwort "try" kommt eine runde Klammer auf, und dann deklariere ich die Ressource, die ich hier in dem "try"-Block gern benutzen möchte. Danach kommt eine runde Klammer zu und dann beginnt der eigentliche Block. In diesem Block kann ich auf diese Ressource zugreifen und wenn ich den Block verlasse, wird die Ressource, wie gesagt, automatisch geschlossen. Benötige ich mehrere Ressourcen, also z.B. zwei Dateien, um aus der einen zu lesen und in die andere zu schreiben, dann deklariere ich mir hier einfach mehrere Ressourcen, hintereinander durch Semikolon getrennt, also ganz normal als einzelne Anweisungen. Das automatische Schließen erfolgt dann in umgekehrter Reihenfolge. Also die Ressource, die ich als letztes deklariert habe, wird als erstes geschlossen. Bleibt noch die Frage: Funktioniert das hier oben mit allen Klassen? Natürlich nicht. Damit von einem Objekt automatisch eine "close-Methode" aufgerufen werden kann, muss das Objekt natürlich eine "close-Methode" haben. Diese Methode ist deklariert in einem Interface "closeable", und es ist auch die einzige Methode, die da drin steht. Sie sehen das "void close", keine Parameter. Eine Klasse muss also keine großen Anforderungen erfüllen, aber sie muss dieses Interface "closeable" implementieren. Wie Sie sehen, gilt das in der Standardbibliothek für ziemlich viele Klassen, und zwar für so ziemlich alle, die irgendetwas mit externen Ressourcen machen, wie z.B. Dateien. Möchten Sie eine selbst geschriebene Klasse mit dem "try with ressources" verwenden, dann müssen auch Sie hier lediglich dieses Interface "closeable" implementieren.

Java 7 Grundkurs

Machen Sie sich mit den Grundlagen der Java-Programmierung vertraut und lernen Sie die Syntax der Sprache sowie das Konzept der objektorientierten Softwareentwicklung kennen.

8 Std. 32 min (66 Videos)
Derzeit sind keine Feedbacks vorhanden...
 

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!