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.
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.
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
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 stream
as final
and you don't need to check if(stream != null)
(it will be always true) –
Prosperity 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 implementjava.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.
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.
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:
null
before closing itfinally
had to contain another try
- catch
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 :-)
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.
Benefits of using try-with-resources:
More readable code and easy to write.
Automatic resource management.
Number of lines of code is reduced.
No need of finally block just to close the resources.
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
}
}
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.
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());
}
© 2022 - 2024 — McMap. All rights reserved.