Java 7 : The new try-with-resources statement

Duke Java Logo

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

This new statement make working with streams and all kind of closeable resources easier. By 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, who 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 informations, about this new statement read try-with-resources specifications.

Related posts:

  1. Java 7 : Languages updates from Project Coin
  2. Java 7 : The new java.util.Objects class
  3. Asynchronous Message Passing in JR
  4. Tip : Add resources dynamically to a ClassLoader
  5. NIO.2 : The new Path API in Java 7
  • Dror Harari

    Well, finally Java copies C#’s ‘using’ block statement (and as usual insists on using a different syntax and hooking it with ‘try’)

    • Baptiste Wicht

      I don’t think this is a bad thing to get the good things of other languages. And hooking it with try is a good thing to keep the language uniform and to not introduce a new keyword.

      • Dror Harari

        I couldn’t agree with you more – I’ve been recommending the use of ‘using’ in C# since it was introduced and am very happy to see it at last in Java (which could benefit much in readability and maintainability by copying more from C#).

        However, as someone who needs to maintain code in both language, I would have much preferred that if an idea is borrowed, it will be borrowed with as little ‘cosmetic’ changes as possible.

        My problem with hooking it with the try block is that I do not think it needs to be linked with the try. Sometimes it matches what I want, other times it does not and I’m left with a funky try block (I must have a ‘catch’ block too, right? even if I do not want to catch anything at that point).

        Anyway, what’s done is done. I hope more good C# constructs will find their way into Java and with more fidelity…

        /d

        • Baptiste Wicht

          Just a little correction, you don’t need to have a catch block with this new try statement ;)

  • Dror Harari

    Well, finally Java copies C#’s ‘using’ block statement (and as usual insists on using a different syntax and hooking it with ‘try’)

    • Baptiste Wicht

      I don’t think this is a bad thing to get the good things of other languages. And hooking it with try is a good thing to keep the language uniform and to not introduce a new keyword.

      • Dror Harari

        I couldn’t agree with you more – I’ve been recommending the use of ‘using’ in C# since it was introduced and am very happy to see it at last in Java (which could benefit much in readability and maintainability by copying more from C#).

        However, as someone who needs to maintain code in both language, I would have much preferred that if an idea is borrowed, it will be borrowed with as little ‘cosmetic’ changes as possible.

        My problem with hooking it with the try block is that I do not think it needs to be linked with the try. Sometimes it matches what I want, other times it does not and I’m left with a funky try block (I must have a ‘catch’ block too, right? even if I do not want to catch anything at that point).

        Anyway, what’s done is done. I hope more good C# constructs will find their way into Java and with more fidelity…

        /d

        • Baptiste Wicht

          Just a little correction, you don’t need to have a catch block with this new try statement ;)

  • http://anotherearlymorning.com Alex Schearer

    Why avoid adding a new keyword? In this case you are overloading the try keyword’s functionality which could make code harder to read — isn’t the whole point of a more limited set of keywords to improve readability? There’s almost something magical going on with AutoCloseable objects I think making that explicit through a keyword is worthwhile.

    • Baptiste Wicht

      The advantage of not adding a new keywork is a greater compatibility with old code. Imagine introducing a new keyword using and a code with a a variable named using, it will not compile in Java 7.

  • http://anotherearlymorning.com Alex Schearer

    Why avoid adding a new keyword? In this case you are overloading the try keyword’s functionality which could make code harder to read — isn’t the whole point of a more limited set of keywords to improve readability? There’s almost something magical going on with AutoCloseable objects I think making that explicit through a keyword is worthwhile.

    • Baptiste Wicht

      The advantage of not adding a new keywork is a greater compatibility with old code. Imagine introducing a new keyword using and a code with a a variable named using, it will not compile in Java 7.

  • Danny Woods

    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.

    Yuk!

    • Danny Woods

      Actually, ignore that… I skimmed over the code and didn’t realise that you’d hacked around that annoyance with a close function.

  • Danny Woods

    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.

    Yuk!

    • Danny Woods

      Actually, ignore that… I skimmed over the code and didn’t realise that you’d hacked around that annoyance with a close function.

  • http://adiguba.developpez.com/ adiGuba

    Hi, (and sorry for my poor english)

    Be careful with your original code.
    Some stream can raise exception on the close() method, and there not proper way to get it programaticaly with your code.

    Actualy, IMHO, the best way to do this is to use one try/finally by resources (this is what the try-with-resources do).

    For example :

    private static void customBufferStreamCopy(File source, File target) throws IOException {
    InputStream fis = new FileInputStream(source);
    try {
    OutputStream fos = new FileOutputStream(target);
    try {
    byte[] buf = new byte[8192];
    int i;

    while ((i = fis.read(buf)) != -1) {
    fos.write(buf, 0, i);
    }

    } finally {
    fos.close();
    }
    } finally {
    fis.close();
    }
    }

    There only one “problem” : exception throwed by close() on finally can hide other exception throwed on the try block.

    a++

  • http://adiguba.developpez.com/ adiGuba

    Hi, (and sorry for my poor english)

    Be careful with your original code.
    Some stream can raise exception on the close() method, and there not proper way to get it programaticaly with your code.

    Actualy, IMHO, the best way to do this is to use one try/finally by resources (this is what the try-with-resources do).

    For example :

    private static void customBufferStreamCopy(File source, File target) throws IOException {
    InputStream fis = new FileInputStream(source);
    try {
    OutputStream fos = new FileOutputStream(target);
    try {
    byte[] buf = new byte[8192];
    int i;

    while ((i = fis.read(buf)) != -1) {
    fos.write(buf, 0, i);
    }

    } finally {
    fos.close();
    }
    } finally {
    fis.close();
    }
    }

    There only one “problem” : exception throwed by close() on finally can hide other exception throwed on the try block.

    a++

  • Pingback: Oracle über die Java Zukunft - Martin Schlegel

  • Pingback: A use case for Java 7 at The Object Teams Blog