Prolafex Nr. 4: Automatisch aufgeräumt

Eine Ressource zu akquirieren und anschließend wieder freizugeben ist gar nicht so einfach. Umso schöner ist es dann, wenn die Programmiersprache einem dabei hilft.

In Pocket speichern vorlesen Druckansicht 16 Kommentare lesen
Lesezeit: 3 Min.
Von
  • Michael Wiedeking

Eine Ressource zu akquirieren und anschließend wieder freizugeben ist gar nicht so einfach. Umso schöner ist es dann, wenn die Programmiersprache einem dabei hilft.

Will man etwa eine Datei öffnen und beschreiben, darf man natürlich vergessen, diese auch wieder zu schließen. In Java könnte das so aussehen:

FileOutputStream out = new FileOutputStream(filename);
out.write(buffer);
out.close();

So einfach das auch aussieht, genau so fehleranfällig ist es. Es könnte ja ein Fehler beim Schreiben auftreten, also muss man irgendwie sicherstellen, dass die Datei auf jeden Fall wieder geschlossen wird.

FileOutputStream out = new FileOutputStream(filename);
try {
out.write(buffer);
} finally {
out.close();
}

So wird aber vorausgesetzt, dass die Datei auch wirklich erfolgreich geöffnet werden konnte. Wird dies – wie in Java üblich – durch eine Ausnahme signalisiert, ist alles in Ordnung. Sollte aber etwa eine Routine dafür verantwortlich sein, den FileOutputStream zu liefern, könnte dieser auch null sein.

FileOutputStream out = createFileOutputStream(filename);
try {
out.write(buffer);
} finally {
if (out != null) {
out.close();
}
}

Nebenbei bemerkt könnte aber auch beim close eine Ausnahme auftreten. Das ist solange kein Problem, solange nicht vorher schon ein Fehler aufgetreten ist; dieser würde nämlich sonst verloren gehen. Also muss man hier auch immer durch das Schreiben entstehende Fehler behandeln und gegebenenfalls um den beim Schließen entstandenen Fehler ergänzen.

FileOutputStream out = new FileOutputStream(filename);
Exception ioException = null;
try {
out.write(buffer);
} catch (IOException e) {
ioException = e;
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
if (ioException != null) {
ioException.addSuppressed(e);
} else {
ioException = e;
}
}
if (ioException != null) {
throw ioException;
}
}
}

Das beschreibt grob, welchen Aufwand man treiben muss, um eine Ressource sicher wieder freizugeben, ohne dass dabei Fehlermeldungen verloren gehen können.

Zum Glück gibt es aber das try-with-resources. Denn mit dessen Hilfe reduziert sich obiger Block fast trivial auf

try (FileOutputStream out = new FileOutputStream(filename)) {
out.write(buffer);
}
Mehr Infos

Pro·la·fex, das; -, -e <engl.-lat.> [Abk. für : programming language feature extra ordinem]: Element einer Programmiersprache, das aus verschiedensten Gründen besondere Beachtung verdient – ohne jedermann gefallen zu müssen.

Dies ist eine große Erleichterung. Einzige Voraussetzung dafür ist, dass die Ressource dem AutoCloseable-Interface genügt. Vergleichbare Varianten von diesem Konstrukt existieren natürlich auch in anderen Programmiersprachen. In C# etwa kann man mit der with-Anweisung Ressourcen automatisch freigeben, wenn Entwickler die IDisposable-Schnittstelle implementieren.

Eigentlich ist es verwunderlich, dass es solange gedauert hat, bis es diese Konstruktion in die Sprachen geschafft hat. Immerhin kann man sich bei Sprachen mit Lambda-Ausdrücken schon jetzt selbst helfen, um derartige Konstruktionen zu implementieren. Einige Sprachen unterstützen dies sogar syntaktisch, sodass sich jene auch optisch nicht von obiger Konstruktion unterscheidet. Aber das ist eine andere Geschichte und will ein andermal erzählt werden. ()