- Java Reference Guide
- Overview
- Table of Contents
- J2SE: Standard Java
- Java Windows NT Services
- Apache Velocity
- Advanced J2SE
- Bytecode Instrumentation
- Dynamic Languages and the JVM
- J2SE 1.5.0: "Tiger"
- Java SE 6
- Java 7
- Setup
- Try-With-Resources
- Project Coin
- Summary
- Core Computer Science Principles in Java (Data Structures)
- Annotations
- Java Generics
- Java New I/O
- Java Sound
- Java Applets
- JavaFX
- Java SE Threading
- Resource Management Using Semaphores
- Java Atomic Operations
- JavaTemplate Pages
- Executing Templates with the JtpExecutor
- Java Cryptography Extensions (JCE)
- Java Database Connectivity (JDBC) API
- Jakarta Commons - Net Class Library
- Jakarta Commons HttpClient
- Apache POI
- Regular Expressions
- JavaMail
- Cool Tools
- Building an Really Simple Syndication (RSS) Java App
- Embedding JavaScript in Java with Rhino
- Logging with Log4J
- Inside Swing
- Swing Components
- SwingX
- Swing Styled Documents
- Web Rendering in Java Swing Applications
- Java Look-and-Feel Graphics Repository
- Java Media Framework
- Quicktime for Java
- Media in Java Review 2008
- External Multimedia in Java
- Graphs and Charts
- Holiday Special: Electronic Greeting Card
- Media Framework: Presenter Application
- Standard Widget Toolkit
- JFace
- Java Performance Tuning
- J2EE Performance Tuning
- Caches and Pools
- Java Caching System
- EHCache
- Java Compression and Decompression
- Obfuscating Java Applications
- Continuous Integration
- Load Testing
- Tomcat Clustering
- High Scalability with Terracotta
- Troubleshooting Production Performance Issues
- Enterprise Java Testing
- Automated Unit Testing with JUnit and Ant
- Unit Testing: Tips From The Trenches
- Custom Ant Tasks
- Extensible Markup Language (XML)
- Java Web Technologies
- Web Frameworks
- Struts 2
- Wicket
- JavaServer Faces
- Distributed Programming / RMI
- Behavior Tracking Servlet Filter
- Servlet Filters
- Building a Robust Java Server
- J2EE: Enterprise Java
- Spring
- Spring 3
- Java Design Patterns
- Model-Driven Architecture
- Enterprise Messaging with ActiveMQ
- Event-Driven Architecture
- XDoclet
- Hibernate
- Developing Standalone Database Applications with Hypersonic DB
- Project Backup
- J2EE Project: Hands-On
- Enterprise Java Beans (EJB) 3.0
- Disaster Recovery
- Java Management Extensions (JMX)
- Service-Oriented Architecture
- Web Services
- RESTful Web Services
- Web Services with Apache CXF
- Atom Syndication
- Project: Building a Web Photo Gallery
- J2ME: Micro Java
- Specialized J2ME
- Optional Packages
- Other Java Technologies
- Derivatives and Competitors
- Java, Engineered for Integration
- Additional Resources
- The World of Java Tools
- Building Java Applications with Ant
- Managing Java Build Lifecycles with Maven
- Acceptance Testing with FitNesse
- Source Control with Subversion
- Inversion of Control and Dependency Injection
- Certification
- Roadmap: Becoming an Enterprise Java Developer
- Roadmap: Becoming an Enterprise Java Developer in 2007
- The Business of Enterprise Software
- JavaOne 2006
- JavaOne 2007
- JavaOne 2008 Wrap-Up
- JavaOne 2009 Wrap-Up
- JavaOne 2010
- JavaOne 2011
- How to Survive in a Turbulent Job Market
- How to Hire the Best Talent
- Unified Modeling Language (UML)
- Cloud Computing
- Amazon EC2 and Java
- MongoDB
- Enterprise Java in 2008 and Beyond
- Predictions for 2018
Try-With-Resources
Last updated Jun 17, 2011.
One thing that has always been tedious for Java developers is cleaning up resources that are contained in a try block. Consider the standard example of executing a database query: it would be nice if we could write that code as follows:
try {
Connection connection = ds.getConnection();
PreparedStatement ps = connection.prepareStatement( "SELECT * FROM TABLE" );
ResultSet rs = ps.executeQuery();
while( rs.next() ) {
...
}
rs.close();
ps.close();
connection.close();
}
catch( Exception e ) {
e.printStackTrace();
}
Of course, what is the big problem with this code? The problem is that if there is a problem with the connection, the prepared statement, or the result set then these resources do not get properly closed. We then find ourselves having to close these resources in a finally block to ensure that whether or not the code succeeds, the resources are closed. But to further complicate things, closing each of these resource can generate exceptions themselves. This turn this simple operation into the following "code overhead":
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
Connection connection = ds.getConnection();
PreparedStatement ps = connection.prepareStatement( "SELECT * FROM TABLE" );
ResultSet rs = ps.executeQuery();
while( rs.next() ) {
...
}
rs.close();
ps.close();
connection.close();
}
catch( Exception e ) {
e.printStackTrace();
}
finally {
try {
if( rs != null ) {
rs.close();
}
}
catch( Exception e ) {
e.printStackTrace();
}
try {
if( ps != null ) {
ps.close();
}
}
catch( Exception e ) {
e.printStackTrace();
}
try {
if( connection != null ) {
connection.close();
}
}
catch( Exception e ) {
e.printStackTrace();
}
}
While this works, it is incredibly messy: not only do you have to close your resources but you have to create them outside the try block, close them in their own try-catch blocks, but you also have to check their state before you do so.
Java 7 introduces what is referred to as try-with-resources, which allows you to define the resources that need to be closed within the try construct itself and then those resources will be automatically closed for you when the try block completes, regardless of whether or not an exception occurred.
The try-with-resources command works as follows:
try { Create objects that can be automatically closed here ) {
//Do stuff ...
}
catch( Exception e ) {
// Handle Exception
}
Add parentheses to the end of the try statement and create objects that can be automatically closed within those parentheses. You can still handle exceptions and even have a finally block, but you do not need to close the resources that are automatically closed. You can create a single object or multiple objects, separating each by a semi-colon.
Looking back at our database connection challenge, here is that same code written using a try-with-resources:
try( Connection connection = ds.getConnection();
PreparedStatement ps = connection.prepareStatement( "SELECT * FROM TABLE" );
ResultSet rs = ps.executeQuery() ) {
while( rs.next() ) {
...
}
}
catch( Exception e ) {
e.printStackTrace();
}
The connection, prepared statement, and result set are all created inside the try command and then the body of the try block iterates over the results. When the block completes, the JVM automatically closes them on your behalf.
The way that this is accomplished is through the java.lang.AutoClosable interface. Any class that implements this interface can be used inside a try-with-resources block and will be closed when the try block is complete when the JVM executes the class's close() method (the only method defined by the AutoCloseable interface.) In Java 7 there are several classes that implement the AutoCloseable interface (see the Javadoc link above), but the ones of note are:
- All of the InputStream, OutputStream, Reader, and Writer derivations
- The database classes: Connection, Statement, PreparedStatement, ResultSet, RowSet, JdbcRowSet
- Most of the socket related classes
- Most of the audio (Java Sound) classes
And of course if you want to create your own class that can be used in such a way, the answer is to implement the AutoCloseable interface and provide an implementation of the close() method.
If you want to follow along at home, listing 1 shows a sample class that uses the new try-with-resources command and listing 2 shows the Maven POM file that builds it. Note that you will need to setup Java 7 in your environment and add it to your PATH before your operating system finds your current Java version.
Listing 1. TryWithResourcesExample.java
package com.javasrc.informit.trywithresourcesexample;
import java.sql.*;
public class TryWithResourcesExample
{
public static void main( String[] args )
{
try( Connection conn = DriverManager.getConnection( "jdbc:hsqldb:file:testdb", "SA", "" );
PreparedStatement ps = conn.prepareStatement( "SELECT * FROM MYTABLE" );
ResultSet rs = ps.executeQuery() )
{
while( rs.next() )
{
// ...
}
}
catch( SQLException e )
{
e.printStackTrace();
}
}
}
Listing 2. pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.javasrc.informit</groupId>
<artifactId>TryWithResourcesExample</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>TryWithResourcesExample</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
In terms of features that make your development life easier, even if just for convenience and clean code, the new try-with-resources has to be at the top of the list for Java 7.


