user2935569 user2935569 - 10 days ago 9
Java Question

Java Exceptions

I am practicing for my java oracle certification test and found this in one of the oracle sample questions. I am not sure why the answer is A and need someone to explain to me.

class MyResource1 implements AutoCloseable {
public void close() throws IOException {
System.out.print("1 ");
}
}
class MyResource2 implements Closeable {
public void close() throws IOException {
throw new IOException();
}
}
public class TestRes {
public static void main(String[] args) {
try (MyResource1 r1 = new MyResource1();
MyResource2 r2 = new MyResource2();) {
System.out.print("T ");
} catch (IOException ioe) {
System.out.print("IOE ");
} finally {
System.out.print("F ");
}
}
}


What is the result?

A) T 1 IOE F
B) T IOE F
C) T IOE 1 F
D) Compilation fails.

Answer

The Java Language Specification 14.20.3.2 Extended try-with-resources says:

A try-with-resources statement with at least one catch clause and/or a finally clause is called an extended try-with-resources statement.

The meaning of an extended try-with-resources statement:

try ResourceSpecification
    Block
[Catches]
[Finally]

is given by the following translation to a basic try-with-resources statement nested inside a try-catch or try-finally or try-catch-finally statement:

try {
    try ResourceSpecification
        Block
}
[Catches]
[Finally]

The effect of the translation is to put the resource specification "inside" the try statement. This allows a catch clause of an extended try-with-resources statement to catch an exception due to the automatic initialization or closing of any resource.

Furthermore, all resources will have been closed (or attempted to be closed) by the time the finally block is executed, in keeping with the intent of the finally keyword.

So, your code is equivalent to:

try {
    try (MyResource1 r1 = new MyResource1()) {
        try (MyResource2 r2 = new MyResource2()) {
            System.out.print("T ");
        }
    }
} catch (IOException ioe) {
    System.out.print("IOE ");
} finally {
    System.out.print("F ");
}

Order of execution is:

  • r1 = new MyResource1()
  • r2 = new MyResource2()
  • System.out.print("T ")
  • r2.close() (completion of r2 try block)
    • throw new IOException()
  • r1.close() (completion of r1 try block)
    • System.out.print("1 ")
  • catch (IOException ioe) (catching exception from r2.close())
    • System.out.print("IOE ")
  • finally
    • System.out.print("F ")