Correct idiom for managing multiple chained resources in try-with-resources block?

Here’s my take on the alternatives:

1)

try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
    bw.write(text);
}

For me, the best thing coming to Java from traditional C++ 15 years ago was that you could trust your program. Even if things are in the muck and going wrong, which they often do, I want the rest of the code to be on best behaviour and smelling of roses. Indeed, the BufferedWriter might throw an exception here. Running out of memory wouldn’t be unusual, for instance. For other decorators, do you know which of the java.io wrapper classes throw a checked exception from their constructors? I don’t. Doesn’t do code understandability much good if you rely upon that sort of obscure knowledge.

Also there’s the “destruction”. If there is an error condition, then you probably don’t want to be flushing rubbish to a file that needs deleting (code for that not shown). Although, of course, deleting the file is also another interesting operation to do as error handling.

Generally you want finally blocks to be as short and reliable as possible. Adding flushes does not help this goal. For many releases some of the buffering classes in the JDK had a bug where an exception from flush within close caused close on the decorated object not be called. Whilst that has been fixed for some time, expect it from other implementations.

2)

try (
    FileWriter fw = new FileWriter(file);
    BufferedWriter bw = new BufferedWriter(fw)
) {
    bw.write(text);
}

We’re still flushing in the implicit finally block (now with repeated close – this gets worse as you add more decorators), but the construction is safe and we have to implicit finally blocks so even a failed flush doesn’t prevent resource release.

3)

try (FileWriter fw = new FileWriter(file)) {
    BufferedWriter bw = new BufferedWriter(fw);
    bw.write(text);
}

There’s a bug here. Should be:

try (FileWriter fw = new FileWriter(file)) {
    BufferedWriter bw = new BufferedWriter(fw);
    bw.write(text);
    bw.flush();
}

Some poorly implemented decorators are in fact resource and will need to be closed reliably. Also some streams may need to be closed in a particular way (perhaps they are doing compression and need to write bits to finish off, and can’t just flush everything.

Verdict

Although 3 is a technically superior solution, software development reasons make 2 the better choice. However, try-with-resource is still an inadequate fix and you should stick with the Execute Around idiom, which should have a clearer syntax with closures in Java SE 8.

Leave a Comment