Apr 28, 2016

Catching and Handling Exceptions in Java

In Java, we have 3 exception handlers: try, catch and finally, to catch and handle the exception. Along with these handlers, one more handler try-with-resources has been introduced in Java 7.

Lets see how to use these exception handlers.
Consider the following example which copies a file from source to destination:



private static void copyFile(File source, File dest) {
        InputStream is = null;
        OutputStream os = null;

        // FileInputStream and FileOutputStream throws FileNotFoundException,
        //which must be caught.
        is = new FileInputStream(source);
        os = new FileOutputStream(dest);
        byte[] buffer = new byte[1024];
        int length;

        // read and write method throws IOException, which must be caught.
        while ((length = is.read(buffer)) > 0) {
            os.write(buffer, 0, length);
        }

        // close method throws IOException, which must be caught.    
        is.close();
        os.close();

}

In the above example, comments have been added on the places where we need to handle the exception thrown by the API.


Try and Catch Blocks

To handle the exceptions, we use try and catch block where try block encloses the code and catch block handles the exceptions thrown from the code.

Below is the syntax for try and catch exception handlers,

try {
   // code
} catch (ExceptionType name) {
...
}


Now, lets incorporate these handlers in the above example

private static void copyFile(File source, File dest) {
 InputStream is = null;
 OutputStream os = null;
 try {
  is = new FileInputStream(source);
  os = new FileOutputStream(dest);
  byte[] buffer = new byte[1024];
  int length;
  while ((length = is.read(buffer)) > 0) {
   os.write(buffer, 0, length);
  }
 } catch (FileNotFoundException e) {
  System.out.println("Caught FileNotFoundException");
 } catch (IOException e) {
  System.out.println("Caught IOException");
 }

 try {
  is.close();
  os.close();
 } catch (IOException e) {
  System.out.println("Caught IOException");
 } 
}

Have you noticed that we have put multiple catch blocks for a single try block for handling different exceptions being thrown by the code in the try block (although we cannot do vice-versa i.e. having multiple try blocks for single catch block). In case of multiple catch blocks, ordering of exception handling is very important. The child exception must always appear before the parent exception otherwise compiler will complain.

In Java7 and later, a single catch block can handle more than one type of exception. This feature reduces code duplication. Different types of exceptions are specified within the braces of catch block,
separated by a vertical bar (|):


catch (IOException|SQLException ex) {
   ...
}

 Remember that in case of multiple exception catch block handler, the catch parameter is implicitly final and therefore you cannot assign any values to it within the catch block.


Finally Block

We can attach a finally block with try-catch block if we want something to be always executed even if an unexpected exception occurs. The code with in the finally block is always executed after the try block, even if an exception is thrown from within the try or catch block. If the 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.
Finally block is mostly used for cleanup purposes, closing open streams,etc.

It is not required to always have both a catch and a finally block. You can have one of them or both of them with a try-block, but not none of them.

Lets incorporate finally block in the above example,


private static void copyFile(File source, File dest) {
       InputStream is = null;
       OutputStream os = null;
       try {
            is = new FileInputStream(source);
            os = new FileOutputStream(dest);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
       } catch (FileNotFoundException e) {
            System.out.println("Caught FileNotFoundException");
       } catch (IOException e) {
            System.out.println("Caught IOException");
       } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    System.out.println("Caught IOException");
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    System.out.println("Caught IOException");
                }
            }
       } 
}


We have moved the code for closing the streams in the finally block so that the stream are closed even if some exception has occurred. Also, in case 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.


Try-with-resources Block 

Java 7 has introduced a new version of try statement for exception handling with resource management. Below is the syntax for try-with-resources block


try(resource-specification)
{
//use the resource
}catch()
{...}

The try statement declares one or more resources which are any object that implements java.lang.AutoCloseable (including all objects which implement java.io.Closeable). A resource is an object that must be closed after the program is finished with it. The java.lang.AutoCloseable contains only close method which gets automatically invoked at runtime.

Lets incorporate try-with-resources in above example,


private static void copyFile(File source, File dest) {
 try (InputStream is = new FileInputStream(source); OutputStream os = new FileOutputStream(dest)) {
  byte[] buffer = new byte[1024];
  int length;
  while ((length = is.read(buffer)) > 0) {
   os.write(buffer, 0, length);
  }
 } catch (FileNotFoundException e) {
  System.out.println("Caught FileNotFoundException");
 } catch (IOException e) {
  System.out.println("Caught IOException");
 }
}


Have you noticed that the code has become too compact with try-with-resources statement containing multiple resource declaration. Multiple resources can be declared within the try parenthesis separated by semicolon. These resources are closed in the reverse order of their declaration. The resources are implicitly declared as final.

A try-with-resources statement can have catch and finally blocks just like an ordinary try statement. The catch or finally blocks run after all the resources are closed even if any any exception has occurred. In case if exceptions occur in both the try block code and the try-with-resources statement, then the exception is thrown from the try block; the exception thrown from try-with-resources statement is suppressed. In Java SE 7 and later, you can retrieve suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block.

That's it! Hope you liked the post. Connect at +Java Territory to stay updated.

0 comments:

Post a Comment