I’m a swiss Master student in Computer Science. I’m very interested in C++, open source projects, Linux, Intel Assembly and Agile. I'm currently working on Eddi, a new programming language that I created to improve my skills in C++. I've also worked a lot on Java technologies (Sprint, Osgi, Play!, ...), but I'm not currently working with Java anymore. Baptiste is a DZone MVB and is not an employee of DZone and has posted 51 posts at DZone. You can read more from them at their website. View Full User Profile

Java 7 : The New try-with-resources Statement

08.26.2010
| 28952 views |
  • submit to reddit

From build 105, the compiler and runtime of the Java 7 Releases have support for the new form of try : try-with-resources, also called ARM (Automatic Resource Management) blocks.

This new statement makes working with streams and all kind of closeable resources easier. For example, in Java, you can have this kind of code :

private static void customBufferStreamCopy(File source, File target) {
InputStream fis = null;
OutputStream fos = null;
try {
fis = new FileInputStream(source);
fos = new FileOutputStream(target);

byte[] buf = new byte[8192];

int i;
while ((i = fis.read(buf)) != -1) {
fos.write(buf, 0, i);
}
}
catch (Exception e) {
e.printStackTrace();
} finally {
close(fis);
close(fos);
}
}

private static void close(Closeable closable) {
if (closable != null) {
try {
closable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

A little bit heavy, isn’t it ? This is only an example, here the management of exceptions is not good.

So let’s use try-with-resources statement to simplify this code, which becomes :

private static void customBufferStreamCopy(File source, File target) {
try (InputStream fis = new FileInputStream(source);
OutputStream fos = new FileOutputStream(target)){

byte[] buf = new byte[8192];

int i;
while ((i = fis.read(buf)) != -1) {
fos.write(buf, 0, i);
}
}
catch (Exception e) {
e.printStackTrace();
}
}

A lot cleaner, no ? With that code, the resources are automatically closed after the try. In the try resources list, you can declare several resources, but all these resources must implement the java.lang.AutoCloseable interface.

If you want more information, about this new statement read try-with-resources specifications.

From http://www.baptiste-wicht.com/2010/08/java-7-try-with-resources-statement/

Published at DZone with permission of Baptiste Wicht, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Igor Sakovich replied on Thu, 2010/08/26 - 1:19am

Nice syntax sugar. But what about java.sql.{Connection,Statements,ResultSet}? Should we wait for next version of jdbc for adding AutoCloseable to such interfaces?

Thomas Mueller replied on Thu, 2010/08/26 - 1:53am

As for java.sql.*, I think that calling close() shouldn't be necessary, except for Connection.close(). If a database or driver requires that you call Statement.close() or ResultSet.close(), then it's the fault of the database. But that's just my view.

Martin Wildam replied on Thu, 2010/08/26 - 3:14am

Yes, indeed looks nicer.

However, I have encapsulated this odd behaviour as one of my first actions when starting doing stream handling with Java, so I already nearly forgot about this odd behaviour. ;-)

Oleg Olegk replied on Thu, 2010/08/26 - 3:45am

In reply to "As for java.sql.*, I think that calling..."

Actually it's not correct.

java.sql.* also should be closed when not needed. If you won't close them you will have leak of resources in case if you use some connection pool.

What you've written is correct only for usual connections - when connection.close() really close the connection.

Thomas Mueller replied on Thu, 2010/08/26 - 5:43am

Still about java.sql: I know the JDBC spec says you should call close (it also says resources are "automatically closed" but it doesn't say when). But in my view, if the system runs out of resources (out of memory or otherwise) because close() was not explicitly called, then it's the fault of this JDBC driver, database, or connection pool.

Chris Knoll replied on Thu, 2010/08/26 - 12:55pm

So, this is basically the 'using' clause from C# but tightly coupled to using a try..catch statement.
That's kinda lame.
Why not just introduce a using-like syntax? Just because MS came up with it first, doesn't mean that it's the devil. Both camps could stand to learn some things from either side.
Man, can't believe it's going on for over a decade, and we still have this attitude that the other side can do no right...
...and another thing, why limit this to things 'AutoCloseable'? Why not make it more generic and define something like...Disposable...so that things that are connections can be closed via dispose but other things that still need to be freed up because maybe they are other types of system resources (such as a UI window) could also be managed via the using clause:
using (InputStream fis = new FileInputStream(source);
           ReportWindow rw = new ReportWindow())
{
    try
    {  
        byte[] buf = new byte[8192];

        fd.showDialog();

        int i;
        while ((i = fis.read(buf)) != -1) {
            // read data into report structure for window
        }
        // Show Window with data.
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

// At this point stream is closed and window is disposed of properly.

Tomi Tuomainen replied on Thu, 2010/08/26 - 2:56pm

Just use Spring JdbcTemplate and you don't have to worry about closing java.sql.* resources.

John J. Franey replied on Thu, 2010/08/26 - 6:48pm in response to: Chris Knoll

Chris,

You are right, of course, but put the soapbox back under the sink. The construct is the same, yes, and it looks like java did indeed learn from C#. However, the only difference is the keyword; c#'s 'using' to java's 'try'. Putting 'try' in the same place as 'using' in your sample gives a java construct, no? I don't expect java designers to add a new keyword ('using') into the language, that would be a dumb move because it would require application code changes. 'try' works in the place of 'using'. It doesn't have anything to do with some reluctance to admit that there is some learning from c#.

Jacek Furmankiewicz replied on Thu, 2010/08/26 - 7:13pm

Ditto.

Can't remember the last time I had to write code like this. Spring rocks.

I hope Oracle doesn't buy them out. :-)

Mike P(Okidoky) replied on Thu, 2010/08/26 - 9:37pm

Do, or do not, there is no try (when not catching the force).

Jonas Olsson replied on Fri, 2010/08/27 - 1:12am

Does the try-with-resources call printStackTrace or not? I hope for not.

Mike P(Okidoky) replied on Fri, 2010/08/27 - 11:37am in response to: Jonas Olsson

Jonas, I don't think it's about catching exceptions, although you obviously can. It's about shoe-horning in resource allocation inside the try statement. If you don't catch the exception(s), then the method will throw those exception(s). It doesn't implicitly invisibly catch exceptions at all.

Chris Knoll replied on Fri, 2010/08/27 - 12:58pm in response to: John J. Franey

John,

 That was a tad bit dismissive, wouldn't you say?  But, to answer your points:

It is a matter of context, and something I felt Java was good at representing usage context (extends is for inheritance, implements for implementation of an interface).   By your reasoning, you're calling the language designers 'dumb' because they made different keywords when it would have been 'reasonable' to just use extends for both inheritance of classes and implementaions of interfaces.  

 To my point:  the context of a try clause is for trapping and handling exceptions. This is a separate concern than cleaning up resources, although these concerns tend to overlap in practice.  I think it would have been more in line with the Java philosophy to have separate keywords for the different  concerns, and I think my 'extends vs implements' point demonstrates this.

 Further, you don't always want to have the bounds of the resoruce be confined to the block of code you are trying to trap errors for.

 Example:

 

using (MyResource res = new MyResource())
{
SomeObject[] theData = null;
try
{
theData = res.GetDataFromDB();
}
catch (Exception ex)
{
//fallback to cache
theData = res.GetDataFromCache()
}
// do work
}

// resource is released.

 So, my point is that as your needs are going to grow in complexity, having a granularity between the 'using' context and the 'error handling' context will let you deal with programming challenges a bit easier than if you are faced with the question 'How do I handle errors and manage these resources at the same time?'.

 

Mike P(Okidoky) replied on Fri, 2010/08/27 - 2:42pm

I like something like this better:
MyResource res = new MyResource() auto close;
Then whenever res goes out of scope, it then automatically calls "close". close could be any other method that takes no arguments.

John J. Franey replied on Fri, 2010/08/27 - 9:06pm in response to: Chris Knoll

Chris, I agree with you:
having a granularity between the 'using' context and the 'error handling' context will let you deal with programming challenges a bit easier than if you are faced with the question 'How do I handle errors and manage these resources at the same time?'.

Then, the following code must also preserve the separation of contexts because it differs from your example, superficially, by only the spelling of the first keyword. The spelling of the keyword does not impact the flow of the control structure.

try (MyResource res = new MyResource())
{
  SomeObject[] theData = null;
  try
  {
    theData = res.GetDataFromDB();
  }
  catch (Exception ex)
  {
      //fallback to cache
      theData = res.GetDataFromCache()
  }
  // do work
}

// resource is released.

Well, I'm sorry about the tone of my first response, but I really am not seeing the strength to an argument that says the C# sample with the spelling 'using' is substantially different from the Java sample with spelling 'try'.

And, I don't think there is much value in discussing which of these spellings is 'better'. There is even less value to such discussion if the impact on existing applications is not taken into account.

Chris Knoll replied on Mon, 2010/08/30 - 9:25am in response to: John J. Franey

John,

 Perhaps you'd like to update your code example with something that will compile?  Unless they are going to say that you don't need a catch/finally clause paired with a try block if you are using the try block to manage resources?

Or do you see my point now?

Using = resource management.

Try = exception handling.

-Chris

 

Leo Mekenkamp replied on Wed, 2011/02/02 - 5:57am

While I am looking forward to the new language features in java, I think your first code block lacks quality. I wrote a blog entry about my gripes.

King Sam replied on Fri, 2012/02/24 - 10:04am

The original Java code is actually even messier: the 'close' calls in your finally block can each generate IOExceptions and, being outside of the scope of the exception handler, must be wrapped with their own try/catch to avoid your method having to declare itself as a thrower. Even worse, to prevent the a failure in closing the first from resulting in the second being left open, you need to do that separately for each close.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.