Jay Taylor's notes
back to listing indexHow to Specify Multiple Resources in a Single Try-With-Resources Statement - DZone Java
[web search]How to Specify Multiple Resources in a Single Try-With-Resources Statement
The ability to specify multiple resources in a single try-with-resources statement is a feature introduced in Java 7. But, it can be fraught with peril if not used carefully. Read on to ensure you do this right every time.
OuterResource.java
package dustin.examples.exceptions;
import static java.lang.System.out;
public class OuterResource implements AutoCloseable
{
private final InnerResource wrappedInnerResource;
public OuterResource(final InnerResource newInnerResource)
{
out.println("OuterResource created.");
wrappedInnerResource = newInnerResource;
}
public OuterResource(
final InnerResource newInnerResource,
final RuntimeException exceptionToThrow)
{
wrappedInnerResource = newInnerResource;
throw exceptionToThrow != null
? exceptionToThrow
: new RuntimeException("OuterResource: No exception provided.");
}
@Override
public void close() throws Exception
{
out.println("OuterResource closed.");
}
@Override
public String toString()
{
return "OuterResource";
}
}
The two classes defined can now be used to demonstrate the difference between correctly declaring instances of each in the same try
-with-resources statement in a semicolon-delimited list and incorrectly nesting instantiation of the inner resource within the constructor of the outer resource. The latter approach doesn't work as well as hoped, because the inner resource —without a locally defined variable — is not treated as a "resource" in terms of invoking its AutoCloseable.close()
method.
The next code listing demonstrates the incorrect approach for instantiating "resources" in the try
-with-resources statement.
Incorrect Approach for Instantiating Resources in try
-with-resources Statement
try (OuterResource outer = new OuterResource(
new InnerResource(), new RuntimeException("OUTER")))
{
out.println(outer);
}
catch (Exception exception)
{
out.println("ERROR: " + exception);
}
When the code above is executed, the output " InnerResource created
" is seen, but no output is ever presented related to the resource's closure. This is because the instance of InnerResource
was instantiated within the call to the constructor of the OuterResource
class and was never assigned to its own separate variable in the resource list of the try
-with-resource statement. With a real resource, the implication of this is that the resource is not closed properly.
The next code listing demonstrates the correct approach for instantiating "resources" in the try
-with-resources statement.
Correct Approach for Instantiating Resources in try
-with-resources Statement
try(InnerResource inner = new InnerResource();
OuterResource outer = new OuterResource(inner, new RuntimeException("OUTER")))
{
out.println(outer);
}
catch (Exception exception)
{
out.println("ERROR: " + exception);
}
When the code above is executed, the output includes both InnerResource created
and InnerResource closed
, because the InnerResource
instance was properly assigned to a variable within the try
-with-resources statement. Therefore, its close()
method is properly called, even when an exception occurs during its instantiation.
The try-with-resources statement section of the Java Tutorials includes examples of correctly specifying the resources in the try
-with-resources as semicolon-delimited individual variable definitions. One example shows this correct approach with java.util.zip.ZipFile and java.io.BufferedWriter. Another example shows this correct approach with instances of java.sql.Statement and java.sql.ResultSet.
The introduction of try
-with-resources in JDK 7 was a welcome addition to the language that it made it easier for Java developers to write resource-safe applications that were not as likely to leak or waste resources. However, when multiple resources are declared within a single try
-with-resources statement, it's important to ensure that each resource is individually instantiated and assigned to its own variable declared within the try
's resource specifier list to ensure that each and every resource is properly closed. A quick way to check this is to ensure that for n, AutoCloseable
is implementing resources specified in the try.
There should be n-1 semicolons, separating those instantiated resources.
Like This Article? Read More From DZone
Published at DZone with permission of Dustin Marx , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.