It enables the use of try-with-resources which is a new feature from Java 7.
Old-school:
InputStream is = null;
try {
is = ...;
// do stuff with is...
} catch (IOException e) {
// handle exception
} finally {
if (is != null) {
try {
is.close();
} catch (IOException innerE) {
// Handle exception
}
}
}
New-school:
try (InputStream is = ...) {
// do stuff with is...
} catch (IOException e) {
// handle exception
}
AutoCloseable objects can be opened in the try-block (within the ()) and will be automatically closed instead of using the finally block as in the code example above.
From the Oracle docs:
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.
So, this means that all objects that are AutoCloseable can be used this way which means that e.g. ResultSet and other resources can be used in the try-with-resources way. IMO, this simplifies the coding and readability.
However, readability is not the killer argument for why to use the new way. I believe that it is the simple fact that the resources are automatically closed. When used prior to Java 7 it was possible to forget to do null-checks or to close the underlying resource - try-with-resources is simply less error-prone.
But, with that said. It is not required to use try-with-resources, it is still possible to use it the old-school way even though I would not recommend it due (since it is both verbose and error-prone).
Answer from wassgren on Stack OverflowVideos
It enables the use of try-with-resources which is a new feature from Java 7.
Old-school:
InputStream is = null;
try {
is = ...;
// do stuff with is...
} catch (IOException e) {
// handle exception
} finally {
if (is != null) {
try {
is.close();
} catch (IOException innerE) {
// Handle exception
}
}
}
New-school:
try (InputStream is = ...) {
// do stuff with is...
} catch (IOException e) {
// handle exception
}
AutoCloseable objects can be opened in the try-block (within the ()) and will be automatically closed instead of using the finally block as in the code example above.
From the Oracle docs:
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.
So, this means that all objects that are AutoCloseable can be used this way which means that e.g. ResultSet and other resources can be used in the try-with-resources way. IMO, this simplifies the coding and readability.
However, readability is not the killer argument for why to use the new way. I believe that it is the simple fact that the resources are automatically closed. When used prior to Java 7 it was possible to forget to do null-checks or to close the underlying resource - try-with-resources is simply less error-prone.
But, with that said. It is not required to use try-with-resources, it is still possible to use it the old-school way even though I would not recommend it due (since it is both verbose and error-prone).
Read the documentation of the try-with-resources feature introduced in Java 7.
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 implementsjava.lang.AutoCloseable, which includes all objects which implementjava.io.Closeable, can be used as a resource.
And the Javadoc of AutoCloseable#close():
Closes this resource, relinquishing any underlying resources. This method is invoked automatically on objects managed by the
try-with-resources statement.
This means you can create your own subtypes of AutoCloseable resources and use them in this statement.
The point of try-with-resources is that:
- The opening of the
Closeableresource is done in thetrystatement - The use of the resource is inside the
trystatement's block close()is called for you automatically.
So your suggested code:
try(Closeable c = map.remove(key)) {}
... doesn't satisfy the point of try-with-resource, since you're not using the resource inside the block. Presumably your Closeable is already open before this statement.
I'm guessing that you have some code whereby a bunch of resources are opened, work is done, then they are all closed by working through the map.
This is OK, and sometimes unavoidable. But it's cleaner, where possible, to have open() and close() in the same method, with the close() in a finally block, so that you can see at a glance that every open() has a corresponding close() and you can be sure that the close() is always called.
MyCloseable c = MyCloseable.open(...);
try{
// do stuff with c;
} finally {
try {
c.close();
} catch (IOException e) {
// ...
}
}
Once you've achieved that, try-with-resources just makes things neater:
try(MyCloseable c = MyCloseable.open(...)) {
// do stuff with c;
}
If your requirements mean you can't get open and close into the same methods, then just stick with an explicit close() and ignore the warning.
I would just ignore this warning, If you are managing close operation on your own, then just call close(). Empty try-with-resource looks weird.
Consider to extend Map so close operation will be performed automatically on remove:
public class CloseableMap<K,V extends Closeable> extends HashMap<K,V> {
@Override
public R remove(K key) {
V resource = super.remove(key);
if (resource != null) {
resource.close();
}
return resource;
}
}
I found this answered on the coin-dev mailing list: http://mail.openjdk.java.net/pipermail/coin-dev/2009-April/001503.html
5. Some failures of the close method can be safely ignored (e.g., closing a file that was open for read). Does the construct provide for this?
No. While this functionality seems attractive, it is not clear that it's worth the added complexity. As a practical matter these “harmless exceptions” rarely if ever occur, so a program will be no more robust if these exceptions are ignored. If you feel you must ignore them, there is a workaround, but it isn't pretty:
static void copy(String src, String dest) throws IOException {
boolean done = false;
try (InputStream in = new FileInputStream(src)) {
try(OutputStream out = new FileOutputStream(dest)) {
byte[] buf = new byte[8192];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
done = true;
} catch(IOException e) {
if (!done)
throw e;
}
}
You could use a decorator pattern here to close the resource quietly:
public class QuietResource<T extends AutoCloseable> implements AutoCloseable{
T resource;
public QuietResource(T resource){
this.resource = resource;
}
public T get(){
return resource;
}
@Override
public void close() {
try {
resource.close();
}catch(Exception e){
// suppress exception
}
}
}
I'm not personally a fan of the resulting syntax, but maybe this works for you:
public static void test(){
try(QuietResource<MyResource> qr = new QuietResource<>(new MyResource())){
MyResource r = qr.get();
r.read();
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
}
You can do better if you're willing to limit yourself to dealing with interfaces and leverage a Dynamic Proxy Class:
public class QuietResource<T> implements InvocationHandler {
private T resource;
@SuppressWarnings("unchecked")
public static <V extends AutoCloseable> V asQuiet(V resource){
return (V) Proxy.newProxyInstance(
resource.getClass().getClassLoader(),
resource.getClass().getInterfaces(),
new QuietResource<V>(resource));
}
public QuietResource(T resource){
this.resource = resource;
}
@Override
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
if(m.getName().equals("close")){
try {
return m.invoke(resource, args);
}catch(Exception e){
System.out.println("Suppressed exception with message: " + e.getCause().getMessage());
// suppress exception
return null;
}
}
return m.invoke(resource, args);
}
}
Then assuming you have:
public interface MyReader extends AutoCloseable{
int read();
}
With an actual resource class:
public class MyResource implements MyReader {
public void close() throws Exception{
throw new Exception("ha!");
}
public int read(){
return 0;
}
}
Calling syntax would look like:
public static void test(){
try(MyReader r = QuietResource.asQuiet(new MyResource())){
r.read();
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
}
You can do better than this if you want to start including libraries, like AOP enablers. These solutions, however, will work out of the box with JDK7 and no other dependencies.