What's the purpose of try-with-resources statements?
Asked Answered
I

7

65

Java 7 has a new feature called try-with-resources. What is it? Why and where we should use it and where we can take advantage of this feature?

The try statement has no catch block which confuses me.

Indoctrinate answered 19/7, 2013 at 6:23 Comment(1)
Take a look at The try-with-resources Statement trailLindner
L
92

It was introduced because of some resources used in Java (like SQL connections or streams) being difficult to be handled properly; as an example, in java 6 to handle a InputStream properly you had to do something like:

InputStream stream = new MyInputStream(...);
try {
    // ... use stream
} catch(IOException e) {
   // handle exception
} finally {
    try {
        if(stream != null) {
            stream.close();
        }
    } catch(IOException e) {
        // handle yet another possible exception
    }
}

Do you notice that ugly double try? now with try-with-resources you can do this:

try (InputStream stream = new MyInputStream(...)){
    // ... use stream
} catch(IOException e) {
   // handle exception
}

and close() is automatically called, if it throws an IOException, it will be supressed (as specified in the Java Language Specification 14.20.3) . Same happens for java.sql.Connection

Lunchroom answered 19/7, 2013 at 6:30 Comment(3)
Personnaly I find the try-with-resources statement quite ugly too. It is even worse when you have multiple resources.Wooton
@Lunchroom if it throws an IOException, it will be handled in the same catch clause This is misleading. If close() throws an exception it is suppressed.Alesiaalessandra
Declare stream as final and you don't need to check if(stream != null) (it will be always true)Prosperity
D
18

As stated in the documentation:

The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.

The following example reads the first line from a file. It uses an instance of BufferedReader to read data from the file. BufferedReader is a resource that must be closed after the program is finished with it:

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly

You can read more from here.

Deviate answered 19/7, 2013 at 6:27 Comment(1)
If the BufferedReader constructor threw an exception (unlikely), the FileReader would not be closed.Pharisee
D
12

Update from 2017 after Java 9 release

Now with Java 9 we have more syntactic sugar and we can have a resource declared outside the try-catch block but still handled properly.

Let's take for example this Java 6 way of handling the resource:

InputStream stream = new MyInputStream(...);
try {
    // ... use stream
} catch(IOException e) {
   // handle exception
} finally {
    try {
        if(stream != null) {
            stream.close();
        }
    } catch(IOException e) {
        // handle yet another possible exception
    }
}

Here we can notice that this code is incredibly ugly as pointed out in other answers.

So the solution in Java 7 was to introduce this try-catch-with-resource:

try (InputStream stream = new MyInputStream(...)){
    // ... use stream
} catch(IOException e) {
   // handle exception
}

This notation is surely way better than the previous one, however we have a problem. If the resource (stream in this case) has been declared previously but we want to be sure that it's handled correctly in this block we need a trick like this:

InputStream stream = new MyInputStream(...)
try (InputStream stream2 = stream) {
   // do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
   // handle exception
}

We can notice that this situation can be addressed only with another piece of ugly code. That's why with Java 9 the Try-With-Resources has been improved introducing a new syntax:

InputStream stream = new MyInputStream(...)
try (stream) {
   // do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
   // handle exception
}

Note that this syntax will result in a compile time error for Java version 8 or minor

This is more "natural" way of writing even though in most use cases we don't need the resource outside the scope of the try block. The only restriction is that the reader variable should be effectively final or just final.

Deodar answered 30/8, 2017 at 14:51 Comment(0)
O
6

In Java, if you use a resource like input or output streams you always have to close it after using. It also can throw exceptions so it has to be in a try catch block. The closing has to be in the finally block. This is a least the way until Java 7. This has several disadvantages:

  • You'd have to check if your ressource is null before closing it
  • The closing itself can throw exceptions so your finally had to contain another try - catch
  • Programmers tend to forget to close their ressources

While the first two are mostly syntax issues, the last one is more critical. So if you use the try-with statement your code gets a lot cleaner and most importantly: Your ressource will always be closed :-)

Obtect answered 19/7, 2013 at 6:31 Comment(0)
F
5

The advantage is you need not explicitly close the resources you have defined in try-with-resources Statement. JVM will take care of it. It will automatically close those resources for you.

Generally problems developers face is to structure the try-catch-finally blocks because even in finally block where we close the resources we have to use try-catch. There are various structures of try-catch-finally statement to help resolve this issue but try-with-resources Statement will basically help you ease your coding structure logic.

Feaze answered 19/7, 2013 at 6:39 Comment(0)
O
2

Benefits of using try-with-resources:

  1. More readable code and easy to write.

  2. Automatic resource management.

  3. Number of lines of code is reduced.

  4. No need of finally block just to close the resources.

  5. We can open multiple resources in try-with-resources statement separated by a semicolon. For example, we can write following code.

    public void sampleTryWithResource() {
        try(Connection dbCon = DriverManager.getConnection("url", "user", "password");
                BufferedReader br = new BufferedReader(new FileReader("C://readfile/input.txt"));) {
            //...Your Business logic
        } catch (Exception e) {
            //...Exception Handling
        }
    }
    
  6. When multiple resources are opened in try-with-resources, it closes them in the reverse order to avoid any dependency issue. You can extend my resource program to prove that.

Otha answered 27/2, 2017 at 8:20 Comment(0)
F
-5

You can try this - if resource is initialized inside try{} it is automatically closed:

try {
            Scanner scanner = new Scanner(new File(csvFile));
            while (scanner.hasNext()) {
                 // do something
            }
            scanner.close();
        }catch(FileNotFoundException fnfe)
        {
            System.err.println(fnfe.getLocalizedMessage());
        }
Felixfeliza answered 1/8, 2016 at 15:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.