- Is it correct that if I'm using a resource that implements the interface java.lang.AutoCloseable I don't need to close it in the finally block and it will be closed even if an exception will be thrown?
Yes.
if so, Is there a precondition that must exist? (e.g. creating the resource inside a try block?)
The resource must be created within the try-with-resources statement (see below).
- What does the try-with-resources statement exactly mean?
Here's a try-with-resources statement:
try (FileReader fr = FileReader(path)) {
// use fr here
}
Note how the initialization of the FileReader is in the try (in the new () part). That's how the statement knows what needs to be closed later.
(More in the tutorial, though I don't like their first example because it relies on A) The fact that the BufferedReader constructor never throws, and B) The fact that BufferedReader will close the FileReader when the BufferedReader is closed. Those are true for BufferedReader, but it's a poor example in the general case.)
The full gritty details, including a translation of what a try-with-resources looks like in the old try/catch/finally format, are in the specification.
Note that you can create multiple resources in the statement; they're closed in reverse order of creation:
try (
FileReader fr =
new FileReader(fileName);
NiftyThingUsingReader nifty =
new NiftyThingUsingReader(fr)
) {
// ...use `nifty` here
}
Although you could write:
try (
NiftyThingUsingReader nifty =
new NiftyThingUsingReader(new FileReader(fileName))
) {
// ...use `nifty` here
}
...you'd have to know for sure that NiftyThingUsingReader(FileReader) never throws an exception, and that NiftyThingUsingReader#close will close the underlying FileReader, because it will not be handled by the try-with-resources itself. If you're unsure, keep them separate, so that the try-with-resources statement closes the FileReader even if the NiftyThingUsingReader(FileReader) constructor throws, and even if NiftyThingUsingReader#close doesn't close it.
The resources don't have to be relying on each other (directly); for instance, this is a fairly common situation where you want both the input and output to be handled:
try (
java.util.zip.ZipFile zf =
new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer =
java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
// Enumerate each entry
for (java.util.Enumeration entries =
zf.entries(); entries.hasMoreElements();) {
// Get the entry name and write it to the output file
String newLine = System.getProperty("line.separator");
String zipEntryName =
((java.util.zip.ZipEntry)entries.nextElement()).getName() +
newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}