Wie man Ressourcen schließt, ist keine Raketenwissenschaft. Dennoch sehe ich in vielen Projekten, auch in meinem eigenen, dass Ressourcen nicht richtig geschlossen werden. Meistens wird vergessen, die Ressourcen in einem Finally-Block zu schließen, oder es wird vergessen, dass das Schließen einer Ressource auch eine Exception auslösen kann, was zu einer Exception-Verschluckung führen kann. In Java 5 wurde die Schnittstelle Closable eingeführt, die einige bequeme Möglichkeiten für das Schließen von Ressourcen bietet. Sehen wir uns ein Beispiel an, das ich in diesem Blog verwenden werde, um zu zeigen, welche Probleme beim Umgang mit Ressourcen auftreten können und wie wir den Beispielcode so umgestalten können, dass er die verwendete Ressource sicher schließt.
public void readFile() throws IOException {
BufferedReader reader = null;
versuchen {
reader = new BufferedReader(new FileReader("foo.txt"));
String line = null;
while((line = reader.readLine()) != null) {
String formattedLine = Parser.parseLine(line);
// andere Dinge tun
}
} finally {
reader.close();
}
}
Obwohl sich der Aufruf von reader.close() in einem finally-Block befindet, ist mit diesem Code noch etwas nicht in Ordnung. Nehmen wir an,
public void copyFile() throws IOException {
BufferedReader reader = null;
versuchen {
reader = new BufferedReader(new FileReader("foo.txt"));
String line = null;
while((line = reader.readLine()) != null) {
String formattedLine = Parser.parseLine(line);
// andere Dinge tun
}
} finally {
versuchen {
reader.close();
} catch(IOException e) {
log.info("Leser schließen fehlgeschlagen.", e);
}
}
Dieser Code ist jetzt sicher vor dem Verschlucken von Ausnahmen und schließt die verwendeten Ressourcen, aber er sieht für mich hässlich aus. Ich mag den verschachtelten try-catch-Block nicht. Wenn wir mehr als eine Ressource schließen müssen, wird es noch schlimmer, da wir so viele verschachtelte try-catch-Blöcke benötigen, wie es Ressourcen gibt. Schauen wir mal, ob wir noch etwas mehr refaktorisieren können. Wie ich bereits sagte, implementieren seit Java 5 alle Ressourcen, die geschlossen werden können, die Schnittstelle Closeable. Dies gibt uns die Möglichkeit, eine Utility-Methode zu erstellen, die das Schließen von Ressourcen übernimmt und das Verschlucken von Ausnahmen verhindert. Nach der Umstrukturierung sieht der Code wie folgt aus:
public void copyFile() throws IOException {
BufferedReader reader = null;
versuchen {
reader = new BufferedReader(new FileReader("foo.txt"));
String line = null;
while((line = reader.readLine()) != null) {
String formattedLine = Parser.parseLine(line);
// andere Dinge tun
}
} finally {
close(reader);
}
}
private void close(Closeable closeable) {
versuchen {
if(closeable != null) {
closeable.close();
}
} catch(IOException e) {
log.info("Leser schließen fehlgeschlagen.", e);
}
}
Wir können die Methode close(Closeable) für jede Closeable-Ressource verwenden, die wir in unserem Code schließen müssen. Wenn wir mehr als eine Ressource in der Methode haben, reicht ein einfacher Aufruf von
public class CloseableTemplate {
public void execute(CloseableCallbackHandler callbackHandler, T closeable) {
versuchen {
callbackHandler.doWithCloseable(closeable);
} finally {
close(closeable);
}
}
private void close(Closeable closeable) {
versuchen {
if(closeable != null) {
closeable.close();
}
} catch(IOException e) {
log.info("Leser schließen fehlgeschlagen.", e);
}
}
}
public interface CloseableCallbackHandler {
void doWithCloseable(T closeable);
}
Die Implementierung der copyFile-Methode würde dann wie folgt aussehen:
public void copyFile() throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("foo.txt"));
new CloseableTemplate().execute(
new CloseableCallbackHandler(){
@Override
public void doWithCloseable(BufferedReader bufferedReader) {
String line = null;
while((line = reader.readLine()) != null) {
String formattedLine = Parser.parseLine(line);
// andere Dinge tun
}
}
}, bufferedReader);
}
}
Wie Sie sehen können, ist der try-finally-Block in der copyFile-Methode nicht mehr notwendig, da das CloseableTemplate dies übernimmt. Wenn Sie also sicher sein wollen, dass die Ressourcen geschlossen sind, schlage ich vor, dass Sie einen ähnlichen Ansatz in Ihrem Projekt verwenden. Lars
Verfasst von
Lars Vonk
Contact



