-2

I'm using Java SDK8 and I created an inputStream and outputStream objects.

Prior to Java SE 7, I could use a finally block to ensure that these resources are closed regardless of whether the try statement completes normally or not. I read that in Java SE 7 and later I can use a try-with-resources statement and in case the resource I'm using implements the interface java.lang.AutoCloseable I don't need to close this resource in the finally block any more.

My questions are: 1. 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? if so, Is there a precondition that must exist? (e.g. creating the resource inside a try block?)
2. What does the try-with-resources statement exactly mean?

Thanks a lot in advance!!

  • related: [Try-with-resources equivalent in Java 1.6](http://stackoverflow.com/questions/23611940/try-with-resources-equivalent-in-java-1-6) – zapl Dec 29 '15 at 00:17
  • 2
    Possible duplicate of [Java7 try-with-resources Statement advantage](http://stackoverflow.com/questions/17739362/java7-try-with-resources-statement-advantage) – mkierc Dec 29 '15 at 00:25
  • A few clicks would have given you the answer – Dici Dec 29 '15 at 00:28

1 Answers1

3
  1. 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).

  1. 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());
    }
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875