Java code bytes: Be resourceful with try-with-resources
It is a very common scenario while implementing a business case in Java, that we have to deal with resources. In this context, a resource (such as a file or socket handle) is encapsulated in an object that we must close after they are used, to release the resource. Traditionally, the onus was on the developer to close all the resources s/he created, that too in proper order to avoid dependency collisions, generally in the following finally block. Failing to do so is not a compilation error, but it can easily lead to a leakage of resource. Though modern static code analysis tools are smart enough to give you a hint, not everyone uses them, and also, those alerts can be easily overlooked.
try-with-resources which was first introduced in Java 7, is a new way to handle (closing of) resources; it makes it easier dealing with resources by automatically taking care of closing of resources in correct order, which were used within a try-catch block.
Let’s take a business case implementation where we need to fetch a given account’s status code from a database. We will first see, how it is done in the traditional way, and then with more resourceful try-with-resources. Later, we will also see a more concise version of it, which got introduced in Java 9.
Resource handling — traditional way (pre Java 7)
We can see above, we have to add a finally block to deal with closing of resource. We have to explicitly check for null before we call the close operation, and also of-course we have to maintain the logical order for closing of resources. The code here is verbose; and I have seen many cases where developers tend to forget to add the finally block for closing resource will leads to resource leaks.
As a side note, if exceptions are thrown here in both try block and finally block, the one thrown from finally block will suppress the other.
Resource handling — with try-with-resources in Java 7/8
The same block of code above, now implemented with try-with-resources, will look like this -
It is noticeable that how concise the new code is, which contributes to the better readability of code. The resource management is done automatically here. We can have multiple resources in the try-with-resources statement, in that case the resource declarations should be separated by a semicolon. These resources will be automatically closed, maintaining the logic order (the one declared last will be closed first etc.).
If exceptions are thrown here in both try-with-resources block and try block, the one thrown from try block will suppress the other. If required, we can retrieve the suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block.
Also, a try-with-resources statement can have catch and finally blocks. Any catch or finally block is run after the resources declared have been closed.
Resource handling — with try-with-resources in Java 9
A more concise version is introduced in Java 9. If we already have a resource declared as a final or effective final, we can use them in try-with-resources without creating any new variables and take advantage of automatic resource management. The same block of code above, now implemented with more concise try-with-resources, will look like -
How it works behind the scene
AutoCloseable interface was introduced with Java 7, and it was specifically designed to work with try-with-resources statements. The Closeable interface which was introduced earlier with Java 5, got modified to extend AutoCloseable. They both have this abstract method close, which the resource should implement and provide a valid implementation for. We can use try-with-resources to close any resource that implement either AutoCloseable or Closeable. All of the JDK resource based classes and interfaces are modified to extend either of these interfaces, making them compatible with try-with-resources out of the box.
Note that, if we are dealing with a resource that doesn’t implement either of AutoCloseable or Closeable, we have to follow the traditional approach for closing the resource.
- try-with-resources facilitates automatic resource management, no need to write an explicit finally block to deal with closing of resources.
- it helps in achieving more concise and legible code.
- we can deal with multiple resources in try-with-resources statement.
- in Java 7/8, these resources must be declared in try-with-resources statement. The resources declared this way are implicitly final.
- in Java 9, we can even use pre-created resources, given the resource reference are declared as a final or are effective final.
- AutoCloseable or Closeable interfaces do behind the scene magic, they work in tandem with try-with-resources statements.
- most of the resource based classes and interfaces in JDK are modified to implement either of AutoCloseable or Closeable, making them compatible try-with-resources out of the box.
- we can have our custom resources implement either of AutoCloseable or Closeable, and make them work with try-with-resources statements.