Try-with-resources Feature in Java

Support for try-with-resources, added in Java 7, allows us to declare resources to be used in a try block while knowing that they would be closed when executed. The try-with-resources statement in Java is a try statement with one or more resources declared. The resource is an object that must be closed once the program is completed. The try-with-resources statement ensures that each resource is closed at the end of the statement execution.

The defined resources must implement the AutoCloseable interface.

Any object that implements java.lang can be passed. In addition, all the objects that implement java.io.Closeable are considered.

Using the try-with-resources method

Simply put, a resource must be declared and initialized inside the attempt to be auto-closed:

try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
    writer.println("Welcome to Codeunderscored");
}

Replacement of the try-catch-finally with try-with-resources

Try-with-resources is a technique that allows you to experiment with different resources. The new try-with-resources functionality replaces the old and verbose try-catch-finally block in a transparent and straightforward approach.

Let’s take a look at some code examples.

The first is a tried-and-true try-catch-finally pattern:

Scanner scan = null;
try {
    scan = new Scanner(new File("code.txt"));
    while (scan .hasNext()) {
        System.out.println(scan .nextLine());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if ( scan != null) {
        scan.close();
    }
}

Here’s a new, super-short solution based on try-with-resources:

try (Scanner scan = new Scanner(new File("code.txt"))) {
    while (scan .hasNext()) {
        System.out.println(scan .nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

try-with-resources with a Variety of Resources

We can declare multiple resources in a try-with-resources block by using a semicolon to separate them:

try (Scanner scan = new Scanner(new File("readCode.txt"));
    PrintWriter pWriter = new PrintWriter(new File("writeCode.txt"))) {
    while (scan scan ner.hasNext()) {
	pWriter.print(scan .nextLine());
    }
}

An AutoCloseable Custom Resource

The class should implement the Closeable or AutoCloseable interfaces and override the close function to create a custom resource that will be handled correctly by a try-with-resources block:

public class CodeResource implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("Code Resource Closed");
    }
}

Resource Order Closure

The first defined/acquired resources will be closed last. Consider the following example of this type of behavior:

1st Resource:

public class CodeAutoCloseableResourcesInitial implements AutoCloseable {

public class CodeAutoCloseableResourcesInitial implements AutoCloseable {

    public CodeAutoCloseableResourcesInitial() {
        System.out.println("Constructor -> AutoCloseableResources_Initial");
    }

    public void exploreCode() {
        System.out.println("Something -> AutoCloseableResources_Initial");
    }

    @Override
    public void close() throws Exception {
        System.out.println("Closed AutoCloseableResources_Initial");
    }
}

2nd Resource

public class CodeAutoCloseableResourcesLast implements AutoCloseable {

    public CodeAutoCloseableResourcesLast() {
        System.out.println("Constructor -> AutoCloseableResources_Last");
    }

    public void exploreCode() {
        System.out.println("Explore -> AutoCloseableResources_Last");
    }

    @Override
    public void close() throws Exception {
        System.out.println("Closed AutoCloseableResources_Last");
    }
}

private void CodeOrderOfClosingResources() throws Exception {
    try (CodeAutoCloseableResourcesFirst firstCode = new CodeAutoCloseableResourcesFirst();
        CodeAutoCloseableResourcesSecond lastCode = new CodeAutoCloseableResourcesLast()) {

        firstCode.exploreCode();
        lastCode.exploreCode();
    }
}

Catch & finally

The catch and finally blocks are still used in a try-with-resources block, and they will work in the same way as they would in a standard try block.

Effectively Final Variables in Java 9

We could only utilize fresh variables inside a try-with-resources block before Java 9:

try (Scanner scan = new Scanner(new File("readCode.txt"));
    PrintWriter pWriter = new PrintWriter(new File("writeCode.txt"))) {
    // omitted
}

It was notably verbose when defining numerous resources, as demonstrated above. We can now utilize final or essentially final variables inside a try-with-resources block as of Java 9 and as part of JEP 213:

final Scanner scan = new Scanner(new File("readCode.txt"));
PrintWriter pWriter = new PrintWriter(new File("writeCode.txt"))
try (scan;pWriter) {
    // omitted
}

Even if a variable isn’t explicitly marked as final, it is essentially final if it doesn’t change after the first assignment.

The scan variable is explicitly declared final, as shown above, to utilize it with the try-with-resources block. The writer variable does not change after the first assignment, even though it is not explicitly final. As a result, we can use the pWriter variable as well. As a result, we no longer need to include an extra finally block for just forwarding the resources’ closure statements. The resources will be closed as soon as the try-catch block is executed.

Try-with-resources syntax :

try(declare resources here) {
    // use resources
}
catch(FileNotFoundException e) {
    // exception handling
}

or

try (resource declaration) {
  // use of the resource
} catch (ExceptionType e1) {
  // catch block
}

As can be seen from the syntax above, the try-with-resources statement is declared by, within the try clause, declaring and instantiating the resource. All exceptions that may be thrown while closing the resource are specified and handled. It’s worth noting that the try-with-resources statement shuts any resources that implement the AutoCloseable interface.

Exceptions

There is a distinction between the try-catch-finally and try-with-resources blocks for exceptions. The method returns the exception thrown in the finally block if an exception is thrown in both tries and finally blocks.

If an exception is thrown in both a try block and a try-with-resources statement in try-with-resources, the method returns the exception thrown in the try block. The try-with-resources exceptions are suppressed. Thus we can say that the try-with-resources block throws suppressed exceptions.

Now, let’s take a look at both alternative circumstances, one of which is shown below as an example:

  • Case 1: A single source of information
  • Case 2: A variety of resources

The sample below saves a string to a file. It writes data to the file using a FileOutputStream object. The resource FileOutputStream must be closed once the program has done utilizing it. As a result, in this example, resource closure is attempted by itself.

import java.io.FileOutputStream;   

 
public class CodeTryWithResources {
    
public static void main(String args[]){      
 
// Using try-with-resources  
try(FileOutputStream fileOutputStream =newFileOutputStream("/java7-new-features/src/abc.txt")){      
String msgString = "Welcome to Codeunderscored!";      
byte byteArray[] = msgString.getBytes(); //converting string into byte array      
fileOutputStream.write(byteArray);  
System.out.println("Message is successfuly written to file!");   
   
}catch(Exception exception){  
       System.out.println(exception);  
}      
}      
}  

Try-with-resources Example: Using Multiple Resources

  import java.io.DataInputStream;  
    import java.io.FileInputStream;  
    import java.io.FileOutputStream;  
    import java.io.InputStream;    

    public class CodeTryWithResources {    
    public static void main(String args[]){      
    
// Using try-with-resources  
    try(    // Using multiple resources  
            FileOutputStream fileOutputStream =new FileOutputStream("/java7-new-features/src/abc.txt");  
            InputStream input = new FileInputStream("/java7-new-features/src/abc.txt")){  

            // -----------------------------Code to write data into file--------------------------------------------//  
            String msgString = "Welcome to Codeunderscored!";      
            byte byteArray[] = msgString.getBytes();  // Converting string into byte array      
            fileOutputStream.write(byteArray);  // Writing  data into file  
            System.out.println("------------ Writing data to file--------------");  
            System.out.println(msgString);  


            // -----------------------------Code for reading data from file---------------------------------------//  
           
	// Creating input stream instance  
            DataInputStream inputStream = new DataInputStream(input);    
            int data = input.available();    
            // Returns an estimate of the number of bytes that can be read from this input stream.   
            byte[] bArray = new byte[data]; //    
            inputStream.read(bArray);    
            String str = new String(bArray); // passing byte array into String constructor
 
            System.out.println("------------Data after reading from the file--------------");  
            System.out.println(str); // display file data

    }catch(Exception exception){  
           System.out.println(exception);  
    }     
    }      
    }   

With a try-with-resources statement, you may utilize catch and finally blocks in the same way with a regular try statement. Catch, or finally, block executes after the stated resources are closed in a try-with-resources statement.

Try-with-resources Example: using finally block

 import java.io.FileOutputStream;    


    public class CodeTryWithResources {    

    public static void main(String args[]){      
    try(    FileOutputStream outputStream=  
      new FileOutputStream("/home/tuts/code/java7-new-features/src/abc.txt")){  

        // -----------------------------Code for writing data into file--------------------------------------------//  

            String msgString = "Welcome to Codeunderscored!";      
            byte bArray[] = msgString.getBytes();  // Conversion of a string into byte array      
            outputStream.write(bArray);  // process of writing  data into file  
            System.out.println("Data writing completed successfully!");  

    }catch(Exception exception){  
           System.out.println(exception);  
    }  
    finally{  
           System.out.println(" Executes finally after closure of declared resources.");  
    }  
    }      
    }  

Example: try-with-resources

import java.io.*;

class Codeunderscored {
  public static void main(String[] args) {
    String line_text;
    try(BufferedReader bReader = new BufferedReader(new FileReader("code.txt"))) {
      while (( line_text = bReader.readLine()) != null) {
        System.out.println("Line =>"+line_text);
      }
    } catch (IOException e) {
      System.out.println("IOException in try block =>" + e.getMessage());
    }
  }
}

We utilize a BufferedReader instance to read data from the code.txt file in this example. Using the try-with-resources statement to declare and instantiate the BufferedReader ensures that its instance is closed regardless of whether the try statement succeeds or fails. If an exception occurs, the exception handling blocks or the throws keyword is used to manage it.

Exceptions that have been suppressed

Exceptions can be thrown from the try-with-resources statement in the example above when:

  • The file test.txt could not be located.
  • The BufferedReader object is being closed.

Because a file read can fail for various reasons at any time, an exception can be thrown from the try block. If both the try block and the try-with-resources statement throw exceptions, the try block exception is thrown, and the try-with-resources statement exception is hidden.

If a try block throws an exception and try-with-resources throws one or more exceptions, the try-with-resources exceptions are silenced. Exceptions thrown by try-with-resources are suppressed exceptions, to put it another way.

Retrieving Exceptions that have been Suppressed

The suppressed exceptions can be obtained in Java 7 and later by invoking the Throwable.getSuppressed() method. The try block’s exception is passed to the process.

This method returns an array of all exceptions that have been suppressed. In the catch block, we obtain the suppressed exceptions.

catch(IOException e) {
  System.out.println("The Exception Thrown=>" + e.getMessage());
  Throwable[] sExceptions = e.getSuppressed();
  for (int i=0; i<sExceptions.length; i++) {
    System.out.println("Exceptions Suppressed=>" + sExceptions[i]);
  }
}

The getSuppress() function of the Throwable class is used to obtain these exceptions. Java provided a new constructor and two new methods to the Throwable class to cope with suppressed exceptions.

Constructor

protected Throwable(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)

It creates a new throwable with the supplied detail message, cause, suppression be it enabled or disabled, and writable stack trace which can either be enabled or disabled.

Method

public final void addSuppressed(Throwable exception)/td&gt;

To convey this exception, it appends the provided exception to the suppressed exceptions. The try-with-resources statement typically calls this thread-safe procedure (automatically and implicitly). The following exceptions are thrown:
IllegalArgumentException: A throwable cannot suppress itself if the exception is throwable. If the exception is null, a NullPointerException is thrown.

public final Throwable[] getSuppressed()

It produces an array with all the exceptions that the try-with-resources command suppressed. An empty array is returned if no exceptions are suppressed or if suppression is disabled.

Example: Program for try-with-resources having a single resource

// Importing all input output classes
import java.io.*;

// Class
class Codeunderscored {

	// Main driver method
	public static void main(String[] args)
	{
		// Try block to check for exceptions
		try (

			// Creating an object of FileOutputStream
			// to write stream or raw data

			// Adding resource
			FileOutputStream fos
			= new FileOutputStream("gfgtextfile.txt")) {

			// Custom string input
			String text
				= "Hello World. This is my java program";

			// Converting string to bytes
			byte arr[] = text.getBytes();

			// Text written in the file
			fos.write(arr);
		}

		// Catch block to handle exceptions
		catch (Exception e) {

			// Display message for the occured exception
			System.out.println(e);
		}

		// Display message for successful execution of
		// program
		System.out.println("Resource are closed and message has been written into the code.txt");
	}
}

The resource is closed, and a message has been written into the code.txt

Example: Program for try-with-resources having multiple resources

// Importing all input output classes
import java.io.*;

// Class
class Codeunderscored {

	// Main driver method
	public static void main(String[] args)
	{
		// Try block to check for exceptions

		// Writing data to a file using FileOutputStream
		// by passing input file as a parameter
		try (FileOutputStream outputStream
			= new FileOutputStream("outputfile.txt");

			// Adding resouce

			// Reading the stream of character from
			BufferedReader br = new BufferedReader(
				new FileReader("code.txt"))) {

			// Declaring a string holding the
			// stream content of the file
			String text;

			// Condition check using readLine() method
			// which holds true till there is content
			// in the input file
			while ((text = br.readLine()) != null) {

				// Reading from input file passed above
				// using getBytes() method
				byte arr[] = text.getBytes();

				// String converted to bytes
				outputStream.write(arr);

				// Copying the content of passed input file
				// 'inputgfgtext' file to code.txt
			}

			// Display message when
			// file is successfully copied
			System.out.println(
				"File content copied to another one.");
		}

		// Catch block to handle generic exceptions
		catch (Exception e) {

			// Display the exception on the
			// console window
			System.out.println(e);
		}

		// Display message for successful execution of the
		// program
		System.out.println("Resource are closed and message has been written into the code.txt");
	}
}

The contents of one file are copied to another. Further, the resource has been closed, and the message has been saved in the code.txt file.

Enhancement to Java 9’s try-with-resources method

The try-with-resources statement has a limitation in Java 7. Within its block, you must declare the resource locally.

try (Scanner scan= new Scanner(new File("readCode.txt"))) {
  // code
}

In Java 7, declaring the resource outside the block would have resulted in an error notice.

Scanner scan = new Scanner(new File("readCode.txt"));
try (scan) {
  // code
}

Java 9 updated the try-with-resources statement to address this issue to allow the resource’s reference to be utilized even if the resource is not specified locally. Without any compilation errors, the code above will now run.

Conclusion

In this article, we examined how to use try-with-resources and how to replace try, catch, and finally with try-with-resources. We also looked at using AutoCloseable to create custom resources and the sequence in which they are closed.

The Try-with-resources statement in Java is a try statement with one or more resources declared. Once your program has finished utilizing it, you must close the resource. A File resource, for example, or a Socket connection resource. The try-with-resources statement ensures that each resource is closed at the end of the statement execution. If we don’t close the resources, it could result in a resource leak, and the program could exhaust its resources.

Any object that implements java.lang can be sent as a resource. Also, all objects that implement java.io.Closeable are considered AutoCloseable.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *