Introduction

In this article, we will take a deep dive into try-with-resources statement in java, its uses, benefits with examples.

Java try-with-resources
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.

Custom resources
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.

Benefits
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.