One of the useful features in Java7 is the Automatic resource management via the try-with-resources statement.
In the olden days thou would (or atleast were supposed to) code like:
void doSomething() throws IOException { OutputStream out = null; try { out = new FileOutputStream(""); out.write(data); } finally { if (out != null) { out.close(); } } }
Which is error prone if you do forget to close the resources.
The new way is:
void doSomethingNew() throws IOException { try (OutputStream out = new FileOutputStream("")) { out.write(data); } }
This is syntactically much more pleasing and does the right thing internally.
Going deep:
The try-with syntax works with any AutoCloseable implementation and you can have multiple resources as well.
The compiler will transform the above code into something like:
void doSomethingNew() throws IOException { OutputStream out = null; Throwable localThrowable1 = null; try { out = new FileOutputStream(""); out.write(blah); } catch (Throwable localThrowable2) { // We keep a reference to which can add a suppressed exception localThrowable1 = localThrowable2; throw localThrowable2; } finally { if (out != null) { if (localThrowable1 != null) { // Already have an exception thrown try { out.close(); } catch (Throwable localThrowable3) { // Add the suppressed exception during close localThrowable1.addSuppressed(localThrowable3); } } else { // Potentially throw an IOException due to failure when close'ing out.close(); } } } }
The pattern is:
- If there are no exception - close() in the finally block OR
- If there are no exception during operation but there is an exception during close() then throw it OR
- If there is an exception thrown then throw it after closing the resource OR
- If there is an exception1 thrown then throw it .. and if there is an exception2 closing the resource.. then exception1.addSuppressed(exception2). This is new in theThrowable class
Sidenote:
There was a huge effort to get closures into Java7 but none of the solutions was light on syntax/complexity. After the backlash over Generics a smaller but better step has been taken.
Sidenote++:
For scala see using. You do not need to wait for language changes to make syntactically pleasing APIs because of curry-ing and other fancy stuff.
More References:
ARM spec
Article on ARM