Exception Handling
IntroductionException: An unwanted unexpected event that disturbs normal flow of the program is called exception. Example:SleepingException TyrePunchuredException FileNotFoundException ...etc
Exception handling doesn't mean repairing an exception. We have to define alternative way to continue rest of the program normally this way of "defining alternative is nothing but exception handling".
Example: Suppose our programming requirement is to read data from remote file locating at London at runtime if London file is not available our program should not be terminated abnormally. We have to provide a local file to continue rest of the program normally. This way of defining alternative is nothing but exception handling.
Example:
Try
{
read data from london file
}
catch(FileNotFoundException e)
{
use local file and continue rest of the program normally
}
}
.
.
.
Runtime stack mechanism:For every thread JVM will create a separate stack all method calls performed by the thread will be stored in that stack. Each entry in the stack is called "one activation record" (or) "stack frame". After completing every method call JVM removes the corresponding entry from the stack. After completing all method calls JVM destroys the empty stack and terminates the program normally.
Example:
class Test
{
public static void main(String[] args){
doStuff();
}
public static void doStuff(){
doMoreStuff();
}
public static void doMoreStuff(){
System.out.println("Hello");
}}
Output:
Hello
Diagram:
![]() Default exception handling in java:If an exception raised inside any method then the method is responsible to create Exception object with the following information.
Example:
class Test
{
public static void main(String[] args){
doStuff();
}
public static void doStuff(){
doMoreStuff();
}
public static void doMoreStuff(){
System.out.println(10/0);
}}
Output:
Runtime error
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Test.doMoreStuff(Test.java:10)
at Test.doStuff(Test.java:7)
at Test.main(Test.java:4)
Diagram:![]() Exception hierarchy:![]() Throwable acts as a root for exception hierarchy. Throwable class contains the following two child classes. ![]()
Exception: Checked Vs Unchecked Exceptions:
Note: RuntimeException and its child classes, Error and its child classes are unchecked and all the remaining are considered as checked exceptions. Partially checked Vs fully checked :A checked exception is said to be fully checked if and only if all its child classes are also checked.Example: 1) IOException 2) InterruptedException A checked exception is said to be partially checked if and only if some of its child classes are unchecked. Example:Exception The only partially checked exceptions available in java are:
![]() Customized exception handling by try catch:
Example:
Try
{
risky code
}
catch(Exception e)
{
handling code
}
Control flow in try catch:
try{
statement1;
statement2;
statement3;
}
catch(X e) {
statement4;
}
statement5;
Various methods to print exception information:Throwable class defines the following methods to print exception information to the console.
![]() Note: Default exception handler internally uses printStackTrace() method to print exception information to the console.
Try with multiple catch blocks:
The way of handling an exception is varied from exception to exception hence for every exception raise a separate catch block is required that is try with multiple catch blocks is possible and recommended to use. Example:
Finally block:
Example:
Try
{
risky code
}
catch(x e)
{
handling code
}
finally
{
cleanup code
}
The speciality of finally block is it will be executed always irrespective of whether the exception raised or not raised and whether handled or not handled.
Example 1:
class Test
{
public static void main(String[] args)
{
try
{
System.out.println("try block executed");
}
catch(ArithmeticException e)
{
System.out.println("catch block executed");
}
finally
{
System.out.println("finally block executed");
}}}
Output:
Try block executed
Finally block executed
Example 2:
class Test
{
public static void main(String[] args)
{
try
{
System.out.println("try block executed");
System.out.println(10/0);
}
catch(ArithmeticException e)
{
System.out.println("catch block executed");
}
finally
{
System.out.println("finally block executed");
}}}
Output:
Try block executed
Catch block executed
Finally block executed
Example 3:
class Test
{
public static void main(String[] args)
{
try
{
System.out.println("try block executed");
System.out.println(10/0);
}
catch(NullPointerException e)
{
System.out.println("catch block executed");
}
finally
{
System.out.println("finally block executed");
}}}
Output:
Try block executed
Finally block executed
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Test.main(Test.java:8)
Return Vs Finally:Even though return present in try or catch blocks first finally will be executed and after that only return statement will be considered that is finally block dominates return statement.
Example:
class Test
{
public static void main(String[] args)
{
try
{
System.out.println("try block executed");
return;
}
catch(ArithmeticException e)
{
System.out.println("catch block executed");
}
finally
{
System.out.println("finally block executed");
}}}
Output:
Try block executed
Finally block executed
If return statement present try catch and finally blocks then finally block return statement will be considered.
Example:
class Test
{
public static void main(String[] args)
{
System.out.println(methodOne());
}
public static int methodOne(){
try
{
System.out.println(10/0);
return 777;
}
catch(ArithmeticException e)
{
return 888;
}
finally{
return 999;
}}}
Output:
999
There is only one situation where the finally block won't be executed is whenever we are using System.exit(0) method. Then JVM itself will be shutdown , in this case finally block won't be executed. i.e., System.exit(0); dominates finally block.
Example:
class Test
{
public static void main(String[] args)
{
try
{
System.out.println("try");
System.exit(0);
}
catch(ArithmeticException e)
{
System.out.println("catch block executed");
}
finally
{
System.out.println("finally block executed");
}}}
Output:
Try
Note : Difference between final, finally, and finalize:Final:
To maintain clean up code faunally block is recommended over finalize() method because we can't expect exact behavior of GC. Control flow in try catch finally:
Example:
class Test
{
public static void main(String[] args){
try{
System.out.println("statement1");
System.out.println("statement2");
System.out.println("statement3");
}
catch(Exception e){
System.out.println("statement4");
}
finally
{
System.out.println("statement5");
}
System.out.println("statement6");
}
}
Control flow in nested try catch finally:
Example:
class Test
{
public static void main(String[] args){
try{
System.out.println("statement1");
System.out.println("statement2");
System.out.println("statement3");
try{
System.out.println("statement4");
System.out.println("statement5");
System.out.println("statement6");
}
catch(ArithmeticException e){
System.out.println("statement7");
}
finally
{
System.out.println("statement8");
}
System.out.println("statement9");
}
catch(Exception e)
{
System.out.println("statement10");
}
finally
{
System.out.println("statement11");
}
System.out.println("statement12");
}
}
Note: if we are not entering into the try block then the finally block won't be executed. Once we entered into the try block without executing finally block we can't come out.
We can take try-catch inside try i.e., nested try-catch is possible
Example:
class Test
{
public static void main(String[] args){
try{
System.out.println(10/0);
}
catch(ArithmeticException e)
{
System.out.println(10/0);
}
finally{
String s=null;
System.out.println(s.length());
}}}
output :
RE:NullPointerException
Note: Default exception handler can handle only one exception at a time and that is the most recently raised exception.
Various possible combinations of try catch finally:
Example 1:
class Test1{
public static void main(String[] args){
try
{}
catch(ArithmeticException e)
{}
}}
Output:
Compile and running successfully.
Example 2:
class Test1{
public static void main(String[] args){
try
{}
catch(ArithmeticException e)
{}
catch(NullPointerException e)
{}
}
}
Output:
Compile and running successfully.
Example 3:
class Test1{
public static void main(String[] args){
try
{}
catch(ArithmeticException e)
{}
catch(ArithmeticException e)
{}
}
}
Output:
Compile time error.
Test1.java:7: exception java.lang.ArithmeticException
has already been caught
catch(ArithmeticException e)
Example 4:
class Test1{
public static void main(String[] args){
try
{}
}
}
Output:
Compile time error
Test1.java:3: 'try' without 'catch' or 'finally'
try
Example 5:
class Test1{
public static void main(String[] args){
catch(Exception e)
{}
}
}
Output:
Compile time error.
Test1.java:3: 'catch' without 'try'
catch(Exception e)
Example 6:
class Test1{
public static void main(String[] args){
try
{}
System.out.println("hello");
catch(Exception e)
{}
}
}
Output:
Compile time error.
Test1.java:3: 'try' without 'catch' or 'finally'
Try
Example 7:
class Test1{
public static void main(String[] args){
try
{}
catch(Exception e)
{}
finally
{}
}
}
Output:
Compile and running successfully.
Example 8:
class Test1{
public static void main(String[] args){
try
{}
finally
{}
}
}
Output:
Compile and running successfully.
Example 9:
class Test1{
public static void main(String[] args){
try
{}
finally
{}
finally
{}
}
}
Output:
Compile time error.
Test1.java:7: 'finally' without 'try'
Finally
Example 10:
class Test1{
public static void main(String[] args){
try
{}
catch(Exception e)
{}
System.out.println("hello");
finally
{}
}
}
Output:
Compile time error.
Test1.java:8: 'finally' without 'try'
Finally
Example 11:
class Test1{
public static void main(String[] args){
try
{}
finally
{}
catch(Exception e)
{}
}
}
Output:
Compile time error.
Test1.java:7: 'catch' without 'try'
catch(Exception e)
Example 12:
class Test1{
public static void main(String[] args){
finally
{}
}
}
Output:
Test1.java:3: 'finally' without 'try'
Finally
Example 13:
class Test1{
public static void main(String[] args){
try
{ try{}
catch(Exception e){}
}
catch(Exception e)
{}
}
}
Output:
Compile and running successfully.
Example 14:
class Test1{
public static void main(String[] args){
try
{ }
catch(Exception e)
{
try{}
finally{}
}
}
}
Output:
Compile and running successfully.
Example 15:
class Test1{
public static void main(String[] args){
try
{ }
catch(Exception e)
{
try{}
catch(Exception e){}
}
finally{
finally{}
}
}
}
Output:
Compile time error.
Test1.java:11: 'finally' without 'try'
finally{}
Example 16:
class Test1{
public static void main(String[] args){
finally{}
try{ }
catch(Exception e){}
}
}
Output:
Compile time error.
Test1.java:3: 'finally' without 'try'
finally{}
Example 17:
class Test1{
public static void main(String[] args){
try{ }
catch(Exception e){}
finally
{
try{}
catch(Exception e){}
finally{}
}
}
}
Output:
Compile and running successfully.
Throw statement: Sometimes we can create Exception object explicitly and we can hand over to the JVM manually by using throw keyword. Example:![]() The result of following 2 programs is exactly same.
Note: In general we can use throw keyword for customized exceptions but not for predefined exceptions. Case 1:throw e; If e refers null then we will get NullPointerException. Example:
After throw statement we can't take any statement directly otherwise we will get compile time error saying unreachable statement. Example:
We can use throw keyword only for Throwable types otherwise we will get compile time error saying incomputable types. Example:
Throws statement: In our program if there is any chance of raising checked exception compulsory we should handle either by try catch or by throws keyword otherwise the code won't compile.
Example:
import java.io.*;
class Test3
{
public static void main(String[] args){
PrinterWriter out=new PrintWriter("abc.txt");
out.println("hello");
}
}
CE :
Unreported exception java.io.FileNotFoundException;
must be caught or declared to be thrown.
Example:
class Test3
{
public static void main(String[] args){
Thread.sleep(5000);
}
}
Unreported exception java.lang.InterruptedException;
must be caught or declared to be thrown.
We can handle this compile time error by using the following 2 ways.
Example:
Note :
Example:
class Test
{
public static void main(String[] args)throws InterruptedException{
doStuff();
}
public static void doStuff()throws InterruptedException{
doMoreStuff();
}
public static void doMoreStuff()throws InterruptedException{
Thread.sleep(5000);
}
}
Output:
Compile and running successfully.
In the above program if we are removing at least one throws keyword then the program won't compile.
Case 1:
Case 3: In our program with in the try block, if there is no chance of rising an exception then we can't right catch block for that exception otherwise we will get compile time error saying exception XXX is never thrown in body of corresponding try statement. But this rule is applicable only for fully checked exception. Example:![]() ![]() Case 4: We can use throws keyword only for constructors and methods but not for classes. Example: ![]() Exception handling keywords summary:
Various possible compile time errors in exception handling:
Customized Exceptions (User defined Exceptions):Sometimes we can create our own exception to meet our programming requirements. Such type of exceptions are called customized exceptions (user defined exceptions). Example:
Program:
class TooYoungException extends RuntimeException
{
TooYoungException(String s)
{
super(s);
}
}
class TooOldException extends RuntimeException
{
TooOldException(String s)
{
super(s);
}
}
class CustomizedExceptionDemo
{
public static void main(String[] args){
int age=Integer.parseInt(args[0]);
if(age>60)
{
throw new TooYoungException("please wait some more time.... u will get best match");
}
else if(age<18)
{
throw new TooOldException("u r age already crossed....no chance of getting married");
}
else
{
System.out.println("you will get match details soon by e-mail");
}}}
Output:
1)E:\scjp>java CustomizedExceptionDemo 61
Exception in thread "main" TooYoungException:
please wait some more time.... u will get best match
at CustomizedExceptionDemo.main(CustomizedExceptionDemo.java:21)
2)E:\scjp>java CustomizedExceptionDemo 27
You will get match details soon by e-mail
3)E:\scjp>java CustomizedExceptionDemo 9
Exception in thread "main" TooOldException:
u r age already crossed....no chance of getting married
at CustomizedExceptionDemo.main(CustomizedExceptionDemo.java:25)
Note: It is highly recommended to maintain our customized exceptions as unchecked by extending RuntimeException. ![]() Top-10 Exceptions:Exceptions are divided into two types.They are: 1) JVM Exceptions: 2) Programatic exceptions: JVM Exceptions:The exceptions which are raised automatically by the jvm whenever a particular event occurs.Example: 1) ArrayIndexOutOfBoundsException(AIOOBE) 2) NullPointerException (NPE). Programatic Exceptions:The exceptions which are raised explicitly by the programmer (or) by the API developer are called programatic exceptions.Example: 1) IllegalArgumentException(IAE). Top 10 Exceptions :
1.7 Version Enhansements :As part of 1.7 version enhansements in Exception Handling the following 2 concepts introduced
try with resourcesUntill 1.5 version it is highly recommended to write finally block to close all resources which are open as part of try block.
BufferedReader br=null;
try{
br=new BufferedReader(new FileReader("abc.txt"));
//use br based on our requirements
}
catch(IOException e) {
// handling code
}
finally {
if(br != null)
br.close();
}
problems in this approach :
The main advantage of "try with resources" isthe resources which are opened as part of try block will be closed automaticallyOnce the control reaches end of the try block either normally or abnormally and hence we are not required to close explicitly due to the complexity of programming will be reduced, it is not required to write finally block explicitly and hence length of the code will be reduced and readability will be improved.
try(BufferedReader br=new BufferedReader(new FileReader("abc.txt")))
{
use be based on our requirement, br will be closed automatically ,
Onec control reaches end of try either normally
or abnormally and we are not required to close explicitly
}
catch(IOException e) {
// handling code
}
We can declare any no of resources but all these resources should be seperated with ;(semicolon)
try(R1 ; R2 ; R3)
{
-------------
-------------
}
All resources should be auto closable resources , a resource is said to be auto closable if and only if the corresponding class implements the java.lang.AutoClosable interface either directly or indirectly. All resource reference variables are implicitly final and hence we can't perform reassignment with in the try block.
try(BufferedReader br=new BufferedReader(new FileReader("abc.txt"))) ;
{
br=new BufferedReader(new FileReader("abc.txt"));
}
output :
CE : Can't reassign a value to final variable br
Untill 1.6 version try should be followed by either catch or finally but 1.7 version we can take only try with resource without catch or finally
try(R)
{ //valid
}
The main advantage of "try with resources" is finally block will become dummy because we are not required to close resources of explicitly.
Multi catch block :Eventhough Multiple Exceptions having same handling code we have to write a seperate catch block for every exceptions, it increases length of the code and reviews readability
try{
-----------------
-----------------
}
catch(ArithmeticException e) {
e.printStackTrace();
}
catch(NullPointerException e) {
e.printStackTrace();
}
catch(ClassCastException e) {
System.out.println(e.getMessage());
}
catch(IOException e) {
System.out.println(e.getMessage());
}
To overcome this problem Sun People introduced "Multi catch block" concept in 1.7 version.
The main advantage of multi catch block is we can write a single catch block , which can handle multiple different exceptions
try{
-----------------
-----------------
}
catch(ArithmeticException | NullPointerException e) {
e.printStackTrace();
}
catch(ClassCastException | IOException e) {
System.out.println(e.getMessage());
}
In multi catch block, there should not be any relation between Exception types(either child to parent Or parent to child Or same type , otherwise we will get Compile time error )
Example: ![]() Exception Propagation :With in a method if an exception raised and if that method doesn't handle that exception then Exception object will be propagated to the caller then caller method is responsible to handle that exceptions. This process is called Exception Propagation.Rethrowing an Exception :To convert the one exception type to another exception type , we can use rethrowing exception concept.
class Test
{
public static void main(String[] args){
try {
System.out.println(10/0);
}
catch(ArithmeticException e) {
throw new NullPointerException();
}
}
}
output:
RE:NPE
|