Introduction
In this article, we will take a deep dive into try-with-resources statement in java, its uses, benefits with examples.
try-with-resources
is a new feature in Java 7 that makes it easier to manage resources that need to be closed.It is used to automatically close resources that have been opened in a
try
block.A resource is an object that needs to be closed after you finish using it. For example, a
FileInputStream
is a resource that needs to be closed. In a normal try-catch block, when a resource is opened in the try
block, it has to be explicitly closed, inside the try
or finally
blocks.
This could lead to a possibility of resource not being closed, if the close()
method is not called, or if an exception is thrown in the try
block before calling close()
.
In Java 7, you can declare and initialize a resource in a try-with-resources
statement. The resource will be automatically closed after the try block exits.
Syntax
Below is the syntax of try-with-resources
statement
try(resource) { // code } catch(Exception e) { // code }
A resource is declared and initialized after try
keyword enclosed between parenthesis.
It is also possible to declare multiple resources inside try
, they should be separated with semi-colon.
Remember that the resources declared inside try-with-resources
will be closed only when they implement AutoCloseable interface.
try-with-resources example
Below is normal try-catch
block that uses a FileInputStream
.
FileInputStream fis = null; try { fis = new FileInputStream("file.png") } catch (IOException e) { // handle the IOException } finally { if(fis != null) { fis.close(); } }
Below is an example of this code to use try-with-resources
try (FileInputStream fis = new FileInputStream("file.png")) { // use the FileInputStream } catch (IOException e) { // handle the IOException }
In this example, the FileInputStream
is the resource that needs to be closed.
The try-with-resources
statement will automatically close the FileInputStream
after the try
block exits.
try with multiple resources
We can open acquire multiple resources inside try-with-resources.
These resources must be separated with semi-colon just like java statements. Example,
try (FileReader r = new FileReader(new File("file.txt")); BufferedReader br = new BufferedReader(r)) { // other code } catch (Exception e) { e.printStackTrace(); }
After the try
block exits, all the resources are closed.
You can create your own resource and use it in
try-with-resources
statement.This resource must implement
AutoCloseable
interface and implement its close()
method. When the try
block exits, close()
method is invoked. Example, class MyReader implements AutoCloseable { @Override public void close() throws Exception { System.out.println("Close called for " + this.getClass().getName()); } }
Now, we can use this resource in try-with-resources
as below
try (MyReader reader = new MyReader()) { // code } catch (Exception e) { e.printStackTrace(); }
When this code executes, below message is printed
Close called for com.codippa.MyReader
If the resource does not implement AutoCloseable
, then you will get a compiler error as below
The resource type MyReader does not implement java.lang.AutoCloseable
Resource closing order
If there are multiple resources acquired in try-with-resources
, then they are closed in reverse order of their declaration or the order in which they are acquired.
This means that the resource acquired last, will be closed first and vice-versa.
To verify, let’s create 2 resources
class MyReader implements AutoCloseable { @Override public void close() throws Exception { System.out.println("Close called for " + this.getClass().getName()); } } class MyReaderTwo implements AutoCloseable { @Override public void close() throws Exception { System.out.println("Close called for " + this.getClass().getName()); } }
Now, use them in try-with-resources
try (MyReader reader = new MyReader(); MyReaderTwo readerTwo = new MyReaderTwo()) { // code } catch (Exception e) { e.printStackTrace(); }
The result is
Close called for com.codippa.MyReaderTwo
Close called for com.codippa.MyReader
Java 9 enhancements
In java 7, the resources declared inside try-with-resources
must be declared locally only. That is, it will not work if the resource is declared before try. Example,
MyReader reader = new MyReader(); try(reader) { // code } catch (Exception e) { e.printStackTrace(); }
This will raise a compiler error.
With java 9, you can use a resource in try-with-resources
, that is declared before, provided it is final or effectively final.
Effectively final means that it is not re-initialized after it is created first. Example,
final MyReader reader = new MyReader(); MyReaderTwo readerTwo = new MyReaderTwo(); try (reader; readerTwo) { // code } catch (Exception e) { e.printStackTrace(); }
Above code is valid. But, you cannot re-initialize MyReaderTwo
, it will raise a compiler error.
Following are the benefits of using try-with-resources.
1. Developer friendly
Using try-with-resources auto closes the resources, thereby eliminating the risk of resources being left open, if developers forget to use
finally
block.2. Less error prone
If there was an error while acquiring a resource and you attempt to close it in
finally
, this may lead to an error. Example, FileReader reader = null; try { reader = new FileReader("file.txt"); // code } catch(IOException e) { // handling code } finally { reader.close(); }
In this example, if there is an error while initializing reader object, then reader.close()
will result in NullPointerException.
Though you can avoid it by checking for null
, but it still requires additional code.
3. Concise
With try-with-resources
, exception handling can be performed in less lines of code as compared to traditional try-catch
.
Example, above code can be written as
try(FileReader reader = new FileReader("file.txt");) { // code } catch(IOException e) { // handling code }
which is clearly shorter.
Hope the article was useful.