This article will explore a very important concept in java programming – Exception handling using try-catch block.
It will cover the requirement of exception handling, syntax of trycatch block, multiple catch blocks, nested trycatch blocks and much more, with examples.
What is exception
Exception is an unexpected and undesirable condition that occurs during program execution.
Example, you are trying to fetch data from a database table.
Connection to the database is successfully established but before query execution, the database service suddenly shuts down.
Result is that the program unexpectedly breaks.

What is exception handling
Exception handling means the measures taken in a program to face unexpected failure conditions so that the program does not break due to any such events.

In a program that has proper exception handling in place, following are the benefits over an application that does not have exceptions handled

  1. You can show your own error messages that are explanatory to the end user instead of the errors generated by JVM.
  2. If the exception is not handled, then JVM prints its error stack trace having method and class name where exception generated and names of methods and classes which called this method in the execution flow.
    A typical error trace will look as below.

    Exception in thread “main” java.io.FileNotFoundException: E:/nofile.txt (The system cannot find the file specified)
    at java.base/java.io.FileInputStream.open0(Native Method)
    at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
    at java.base/java.io.FileReader.<init>(FileReader.java:75)
    at FileDemo.readFile(FileDemo.java:16)
    at FileDemo.main(FileDemo.java:20)

    This information displays your application details such as method and class names, line numbers etc., which is not something that you would like to expose to the users.

  3. Exception handling enables a program to execute normally even after the point at which exception occurred so that it shuts down gracefully as opposed to the application without exception handling which terminates abruptly after an exception.
  4. With exception handling, you can close the resources(such as database/network connections, files etc.) if the program does not execute as expected.

If a program does not have exception handling and some exception occurs, then default exception handler of JVM comes into picture and it prints the complete stack trace of the exception starting from the point where exception originated till main method as shown above.

Exception handling in java
Java provides try, catch keywords to handle exceptions. Any code that the developer thinks as risky or that may raise an exception is placed inside try block.

try block is a set of statements enclosed between curly braces and preceded with try keyword. try block is followed by a catch block which contains the type of exception that this block will handle.

During the execution of try block, if an exception occurs, then the control is transferred directly to the catch block which handles the type of exception raised and no further statements in the try block are executed.
Example,

try {
// statement 1
// statement 2
– – –
} catch(IOException e) {
// exception handling code
}

Above try-catch block contains some statements that the developer considers to be risky.
Note that the catch keyword is followed by a java.io.IOException.
Here it is declaring that any exception which is of type java.io.IOException or its sub-type will be caught and handled by me.

Following the name of the exception type is a user defined variable which is an object of the exception type caught by the catch block.
It contains the exception details when it occurs. You can use it to print the complete stack trace by calling printStackTrace method on this variable.

It is not mandatory to name it e, you can name it anything as per java variable naming rules.
Remember that if the exception is of any other type then the catch block will not be able to handle the exception.
Multiple catch blocks
A try block may be followed by one or more catch blocks each handling different type of exception.
Thus, one catch block may be handling java.io.IOException, another may be handling java.sql.SQLException, a third one might be handling java.lang.InterruptedException etc. Example,

try {
// statement 1
// statement 2

} catch(IOException e) {
// exception handling code
} catch(SQLException e) {
// exception handling code
} catch(InterruptedException e) {
// exception handling code
}

When there are multiple catch blocks handling different type of exceptions, then the order of these blocks is important.

If a catch block handles an exception, then you can not place another catch block that handles an exception of its sub-type below it since it is already handled by the upper catch block.
Example,
if a catch block handles java.io.IOException then you can not place another catch block that handles java.io.FileNotFoundException since it is a sub-class of the former.
But reverse is possible, that is you can place the catch block with sub-type before the catch block with super type.
Thus, following is illegal

try {
// statement 1
// statement 2
– – –
} catch(IOException e) {
// exception handling code
} catch(FileNotFoundException e) {
// wrong!!! already caught above
}

while this is perfectly legal

try {
// statement 1
// statement 2
– – –
} catch(FileNotFoundException e) {
// exception handling code
} catch(IOException e) {
// exception handling code
}

Exception handling program in java
Below is an example program which demonstrates how to use try-catch block to handle an exception in java.
The program tries to read a file. Now when reading a file, it might happen that the file is not located at the specified location or it is corrupt.
First condition will raise a java.io.FileNotFoundException and second will raise a java.io.IOException. Both are handled in the program.

public class ExceptionDemo {
   public static void main(String[] args) {
     String fileName = "E:/nofile.txt";
     try {
       System.out.println("Reading file...");
       FileReader reader = new FileReader(new File(fileName));
       reader.read();
       System.out.println("File read...");
     } catch (FileNotFoundException e) {
       System.out.println("Error: File '"+fileName+"' not found");
     } catch (IOException e) {
       System.out.println("IO error while reading file");
     }
     System.out.println("Risky code executed");
   }
}

If the file at the given path exists then the program output will be

Reading file…
File read…
Risky code executed…

And if the file to be read is not present at the given location(exception condition), then the output will be

Reading file…
Error: File ‘E:/nofile.txt’ not found
Risky code executed…

Note that as soon as exception occurs, the control is transferred to the catch block and the statements in the try block after the line where exception occurred are not executed.
And whether exception occurs or not, the code after catch block is executed.
finally block
A finally block is a set of statements enclosed within curly braces preceded with finally keyword.
A finally block is placed after catch block or directly after try block if a catch corresponding to try is not present. But it can not be written between try and catch.

A try block should be followed either by a catch block or finally block or both otherwise there will be a compiler error.

finally block is guaranteed to execute. A finally block will execute even if an exception arises inside a catch block.

Thus, use of finally block is for cleanup related tasks such as closing a database connection, files or network connections.
Above program modified to use finally block will be as below.

public class ExceptionDemo {
   public static void main(String[] args) {
     String fileName = "E:/nofile.txt";
     FileReader reader = null;
     try {
       System.out.println("Reading file...");
       reader = new FileReader(new File(fileName));
       reader.read();
       System.out.println("File read...");
     } catch (FileNotFoundException e) {
       System.out.println("Error: File '"+fileName+"' not found");
     } catch (IOException e) {
       System.out.println("IO error while reading file");
     } finally {
       System.out.println("Executing finally block...");
       // close reader
       if(reader != null) {
         reader.close();
       }
     }
     System.out.println("Risky code executed");
   }
}

Output now will be

Reading file…
File read…
Executing finally block…
Risky code executed…

Assuming that the execution is without any exception. Even if there is an exception, finally block will execute.
As mentioned earlier, a try block may be followed by one or more catch blocks but only one finally block can be associated with a try-catch block or a try block.
Nested try-catch
A try block can be placed inside another try-catch block. This inner try block may itself have a try-catch block. This is called nesting of try-catch blocks.

In the case of nested try blocks, each block should have its own associated catch or finally blocks or both. Example,

// outer try block
try {
// first level nesting
try {
// second level nesting
try {

} finally {

// second level nesting end
} catch(Exception inner) {

}  // first level nesting end
catch(Exception e) {

// outer try end

Exception hierarchy in java
Exception classes in java are organized with a proper hierarchy with java.lang.Throwable as the super class of all exception classes.
This class has two child classes java.lang.Error and java.lang.Exception. These classes further categorize all the exception classes.

Classes which extend java.lang.Error represent abnormal conditions which are not raised by the program such as java.lang.OutOfMemoryError which occurs when the application takes more than available memory.

exception hierarchy in java Child classes of java.lang.Exception are further sub-divided into two groups

1. java.lang.RuntimeException
Super class of all exceptions that occur due to programmatic errors such as

  • java.lang.NullPointerException caused by calling a method or a field on a null reference.
    More on this exception here.
  • java.lang.ArrayIndexOutOfBoundsException by accessing an array index past its size
  • java.lang.ArithmeticException due to division of an integer by zero etc.

Sub-classes of java.lang.RuntimeException are also called unchecked exceptions since they do not need to be caught or declared in method declarations if not handled by a try-catch block.

2. Other child classes
Classes which directly or indirectly extend java.lang.Exception are called checked exceptions.
These exceptions need to handled or declared to be thrown if not handled.
Example,
Suppose a method reads a file using java.lang.FileReader as in our earlier example.
Signature of the constructor of this class is public FileReader(String fileName) throws FileNotFoundException.
It declares that it may throw a java.io.FileNotFoundException.

Thus, if you use this constructor to create its object, you need to handle this exception by placing it in a try-catch block or your code also needs to add a throws clause.
This is because java.io.FileNotFoundException indirectly extends java.lang.Exception and hence it is a checked exception.
Creating custom exceptions
Besides using built in exceptions, it is also possible to create our own exceptions. In fact, most applications create custom exceptions which is used throughout the application.
This is done so that there is uniformity across the application.

To create your own exception, create a class and make it a child class of java.lang.Exception so that it becomes a checked exception which needs to be handled or declared in the application code.
Hope you liked this article and learnt from it.
Hit the clap below to show your appreciation. Write comments for any additions or mistakes.

Leave a Reply