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 try
–catch
block, multiple catch
blocks, nested try
–catch
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.
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
- You can show your own error messages that are explanatory to the end user instead of the errors generated by JVM.
- 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.
- 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.
- 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.
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.
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
.
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.
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 sizejava.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.