Search code examples
javatry-with-resources

When does try-with-resources close the resource?


I'm preparing myself for fall exam in Object Oriented Programming and one type of tasks we are given is providing output from code which usually consists of some Exception handling problems.

Now my question is when does try-with-resources close it's resource because my output is strictly dependent on output from class that implements AutoCloseable.

In provided code, what I don't understand why "close 1" output comes before "close 40", or why is object A(40) closed at the end of this block. Is it because A(50) is same type as A(40)?

My main question when does the AutoCloseable close the given resource, like in example m1 when i=1:

1) A(1) is created 1b) Try block is executed 2) A(1) is closed 3) ArrayIndexOutOfBoundsException is handled?

public class Main {
    public static void main(String[] args) {
          int[] arr = new int[] { 15, 10 };
          for(int i=1; i>=-1; i--){
              try(A a40 = new A(40)) {
                  m1(arr, i);
                  A a50 = new A(50);
              }
              catch(ArrayIndexOutOfBoundsException e) {
                System.out.println("array exc");
              }
              catch(Exception e) {
                System.out.println("main exc");
                break;
              }
              finally {
                System.out.println("main finally");
              }
          }
          System.out.println("main done");
        }

        private static void m1(int[] arr, int i) throws Exception {
          try(A a1 = new A(i)) {
            m2(arr[i] + arr[i+1], i);
          }
          catch(ArrayIndexOutOfBoundsException e) {
            System.out.println("m1 exc");
          }
          System.out.println("m1 done");
        }

        private static int m2(int x, int y)  {
           int r = 0;
           try{
               A a2 = new A(x+y);
               r = x / y;
           }
           finally {
            System.out.println("m2 finally");
           }
           System.out.println("m2 done");
           return r;
        }
}

And class A which implements AutoCloseable:

public class A implements AutoCloseable {
      private int x;
      public A(int x){
        this.x = x;
           System.out.println("A " + x);
      }
      @Override
      public void close() throws Exception {
        System.out.println("close " + x);
      }
}

Here is output of provided code:

A 40
A 1
close 1
m1 exc
m1 done
A 50
close 40
main finally
A 40
A 0
A 25
m2 finally
close 0
close 40
main exc
main finally
main done

Solution

  • The specification is pretty clear on this.

    14.20.3. try-with-resources

    A try-with-resources statement is parameterized with local variables (known as resources) that are initialized before execution of the try block and closed automatically, in the reverse order from which they were initialized, after execution of the try block.

    Your example is a bit convoluted. Try to simplify it. There are two scenarios you are interested in: an exception thrown in the try block, an exception isn't thrown in the try block. You debugging messages is informative, so you will be able to track the flow easily.

    You may want to look into decompiled .classes to see what actually was generated.