Try With Resources in Java 7 and Above

Introduction

Java try-with-resourcesTry with Resources in Java 7 and above allows for automatic closing of resources that implement java.lang.AutoCloseable or the more familiar java.io.Closeable (which extends AutoCloseable)

Anyone through a basic Java course will be familiar with this block of code. Open a text file to write data and close it when done.

The method attempts to write to a file and throws any exception that hinders in achieving this. The finally block ensures that no file handle is left open by this method. But close() can throw an exception if closing the file fails. The above code will then inform the caller of this method about a problem with closing the file rather than the inability to write to the file.

An obvious and good enough solution would be to surround the close in a try catch and handle the exception. Good programmers are dime a dozen but the ones who consider programming an art will not be pleased with this solution. See this example where you try to execute a query on a database using a connection from a pool and have to handle closing of the ResultSet, the PreparedStatement and the database connection. This is messy and illegible at the very least.

 

Using the Try With Resources construct

The Java people give you Try With Resources construct (JDK 1.7 and above). To quote, “A try-with-resources statement is parameterized with variables (known as resources) that are initialized before execution of the try block and closed automatically, in the reverse order from which they were initialized, after execution of the try block.”

Notice how the file stream (a.k.a the resource) initializes in a parameterized try statement. This initialization defines the FileOutputStream object as a resource. When a try-with-resources block is finished or catches an exception, it automatically attempts to close all associated resources (in reverse order of initialization).

In larger applications all errors resulting from user operations or other system actions are either logged centrally or shown to end user in a friendly way. This means that methods like these propagate errors to their callers. Having a try-with-resources that closes the resources removes a need for verbose code while propagating the real reason up the stack. See Exception Handling section later for more info. Our database example with this new construct looks like this.

The connection, prepared statement and result set are handled as resources. The connection’s close method should handle the returning to pool logic. We use an extended try-with-resources (with multiple resources, see below) to catch the SQLException and add the sql query to the message along with the exception’s cause. Much much cleaner than before.

Try with Resources for Multiple Resource

You can declare multiple resources in a try block in the following manner. The try initialization block can have any number of resources resulting in either null or non-null resources.

The try-with-resources construct is just syntactic sugar and converts to try-catch-finally construct with extra logic to handle proper closing or resources and exception handling. Read the Java Language Specification for more insight in to the implementation detail.

Extended Try With Resources

A try-with-resources statement with no catch clauses or finally clause is called a basic try-with-resources. A try-with-resources with at least one catch clause and/or a finally clause is called an extended try-with-resources statement. The catch clause(s) and/or finally help in handling of errors related to initialization/closing of resources. This internally translates to a try-with-resources statement enclosed within a try-catch-finally block.

Key points

  • All resources are implicitly declared final.
  • All resources are initialized left to right and closed in the reverse order.
  • All resources should be a subtype of java.lang.AutoCloseable .
  • A resource’s scope starts from it’s declaration onwards through the initialization block followed by the try block. In the example above, fos  is available to be used in initializing the BufferedOutputStream . But these resources will not be available to be used in an extended try-with-resources statement’s catch or finally blocks.
  • Only resources with non-null initialization are closed.
  • If a resource fails to initialize (an exception), then all resources already initialized are closed (in the reverse order).
  • A successful initialization of all resources is followed by execution of try block and subsequent close of all non-null resources.
  • An exception from closing of a resource is suppressed if there is an exception already thrown by either the initializer, try block or closing of a resource.

Exception Handling

A try-with-resources statement not only handles the issue of propagating the actual exception but also makes available other exceptions thrown along the way. Exceptions can possibly be thrown by the following blocks:

  • Initialization block
  • Try block
  • Auto-closing of resources

The first exception thrown during execution is considered the primary exception which could be thrown by either of these blocks. Any subsequent exception is suppressed and added to the primary exception. E.g. If initialization is successful and try block throws an exception, all subsequent exceptions that might be thrown when closing the resources will be added as suppressed exceptions to the try block exception. Suppressed exceptions can be accessed using Throwable.getSuppressed()

Conclusion

try-with-resources offers much cleaner handling of resources and integrated exception handling with the only requirement that the resource implement java.lang.AutoCloseable .