Tuesday, July 25, 2017

Exception thrown from try{} block & finally{} block, Try-Catch-Finally vs Try-with-resources

Try-Catch-Finally

private static void printFile() throws IOException {
    InputStream input = null;

    try {
        input = new FileInputStream("file.txt");

        int data = input.read();
        while(data != -1){
            System.out.print((char) data);
            data = input.read();
        }
    } finally {
        if(input != null){
            input.close();
        }
    }
}
The code marked in bold is where the code can throw an Exception. As you can see, that can happen in 3 places inside the try-block, and 1 place inside the finally-block.
The finally block is always executed no matter if an exception is thrown from the try block or not. That means, that the InputStream is closed no matter what happens in the try block. Or, attempted closed that is. The InputStream's close() method may throw an exception too, if closing it fails.
Imagine that an exception is thrown from inside the try block. Then the finally block is executed. Imagine then, that an exception is also thrown from the finally block. Which exception do you think is propagated up the call stack?
The exception thrown from the finally block would be propagated up the call stack, even if the exception thrown from the try block would probably be more relevant to propagate.

( ///
If your code has a return statement inside the try or catch block, the code inside the finally-block will get executed before returning from the method.
No matter whether an exception is thrown or not inside the try or catch block the code inside the finally-block is executed.

Note: If an exception is thrown inside a finally block, and it is not caught, then that finally block is interrupted just like the try-block and catch-block is. That is why the previous example had the reader.close() method call in the finally block wrapped in a try-catch block:
    } finally {
            if(reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    //do something clever with the exception
                }
            }
            System.out.println("--- File End ---");
        }
That way the System.out.println("--- File End ---"); method call will always be executed. If no unchecked exceptions are thrown that is.
@reference_2_tutorials.jenkov.com
Basic try-catch-finally Exception Handling in Java
/// )

Try-with-resources

private static void printFileJava7() throws IOException {

    try(FileInputStream input = new FileInputStream("file.txt")) {

        int data = input.read();
        while(data != -1){
            System.out.print((char) data);
            data = input.read();
        }
    }
}
When the try block finishes the FileInputStream will be closed automatically. This is possible because FileInputStream implements the Java interface java.lang.AutoCloseable. All classes implementing this interface can be used inside the try-with-resources construct.
If an exception is thrown both from inside the try-with-resources block, and when the FileInputStream is closed (when close() is called), the exception thrown inside the try block is thrown to the outside world. The exception thrown when the FileInputStream was closed is suppressed. This is opposite of what happens in the example first in this text, using the old style exception handling (closing the resources in the finally block).

@reference_1_tutorials.jenkov.com
Try-with-resources in Java 7

Using Multiple Resources

You can use multiple resources inside a try-with-resources block and have them all automatically closed. Here is an example:
private static void printFileJava7() throws IOException {

    try(  FileInputStream     input         = new FileInputStream("file.txt");
          BufferedInputStream bufferedInput = new BufferedInputStream(input)
    ) {

        int data = bufferedInput.read();
        while(data != -1){
            System.out.print((char) data);
    data = bufferedInput.read();
        }
    }
}
This example creates two resources inside the parentheses after the try keyword. An FileInputStream and a BufferedInputStream. Both of these resources will be closed automatically when execution leaves the try block.
The resources will be closed in reverse order of the order in which they are created / listed inside the parentheses. First the BufferedInputStream will be closed, then the FileInputStream.

No comments:

Post a Comment