Exception Handling
Exception Handling
1. Introduction
2. Runtime stack mechanism
3. Default exception handling in java
4. Exception hierarchy
5. Customized exception handling by try
catch
6. Control flow in try catch
7. Methods to print exception information
8. Try with multiple catch blocks
9. Finally
10. Difference between final, finally,
finalize
11. Control flow in try catch finally
12. Control flow in nested try catch
finally
13. Various possible combinations of try
catch finally
14. throw keyword
15. throws keyword
16. Exception handling keywords
summary
17. Various possible compile time errors
in exception handling
18. Customized exceptions
19. Top-10 exceptions
20. 1.7 Version Enhansements
1. try with resources
2. multi catch block
21. Exception Propagation
22. Rethrowing an Exception
Introduction
Exception: An unwanted unexpected event
that disturbs normal flow of the program is
called exception.
Example:
SleepingException
TyrePunchuredException
FileNotFoundException ...etc
It is highly recommended to handle
exceptions. The main objective of
exception handling is graceful (normal)
termination of the program.
What is the meaning of exception handling?
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
}
}
.
.
.
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.
1. Name of the exception.
2. Description of the exception.
3. Location of the exception.(StackTrace)
4. After creating that Exception object the
method handovers that object to the JVM.
5. JVM checks whether the method contains
any exception handling code or not. If
method won't contain any handling code
then JVM terminates that method
abnormally and removes corresponding
entry form the stack.
6. JVM identifies the caller method and
checks whether the caller method contain
any handling code or not. If the caller
method also does not contain handling
code then JVM terminates that caller also
abnormally and the removes
corresponding entry from the stack.
7. This process will be continued until
main() method and if the main() method
also doesn't contain any exception
handling code then JVM terminates main()
method and removes corresponding entry
from the stack.
8. Then JVM handovers the responsibility of
exception handling to the default
exception handler.
9. Default exception handler just print
exception information to the console in the
following formats and terminates the
program abnormally.
Name of exception: description
Location of exception (stack trace)
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:
Error:
Most of the cases errors are not caused by our
program these are due to lack of system
resources and these are non recoverable.
Ex : If OutOfMemoryError occurs being a
programmer we can't do anything the program
will be terminated abnormally.
System Admin or Server Admin is responsible
to raise/increase heap memory.
Try
{
risky code
}
catch(Exception e)
{
handling code
}
Without try catch With try catch
class Test{
public static void
class Test main(String[] args){
{ System.out.println("statem
public static void ent1");
main(String[] args){ try{
System.out.println("statem System.out.println(10/0);
ent1"); }
System.out.println(10/0); catch(ArithmeticException
System.out.println("statem e){
ent3"); System.out.println(10/2);
} }
} System.out.println("statem
output: ent3");
statement1 }}
RE:AE:/by zero Output:
at Test.main() statement1
5
Abnormal termination. statement3
Normal termination.
Control flow in try catch:
try{
statement1;
statement2;
statement3;
}
catch(X e) {
statement4;
}
statement5;
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 :
System.exit(0);
insteadof zero, we can take any integer value
zero means normal termination , non-zero
means abnormal termination
this status code internally used by JVM,
whether it is zero or non-zero there is no
change in the result and effect is same
Difference between final, finally, and
finalize:
Final:
Final is the modifier applicable for class,
methods and variables.
If a class declared as the final then child
class creation is not possible.
If a method declared as the final then
overriding of that method is not possible.
If a variable declared as the final then
reassignment is not possible.
Finally:
It is the block always associated with try
catch to maintain clean up code which
should be executed always irrespective of
whether exception raised or not raised and
whether handled or not handled.
Finalize:
It is a method which should be called by
garbage collector always just before
destroying an object to perform cleanup
activities.
Note:
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");
}
}
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");
}
}
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:
1. Whenever we are writing try block
compulsory we should write either catch
or finally.
i.e., try without catch or finally is invalid.
2. Whenever we are writing catch block
compulsory we should write try.
i.e., catch without try is invalid.
3. Whenever we are writing finally block
compulsory we should write try.
i.e., finally without try is invalid.
4. In try-catch-finally order is important.
5. With in the try-catch -finally blocks we
can take try-catch-finally.
i.e., nesting of try-catch-finally is possible.
6. For try-catch-finally blocks curly braces
are mandatory.
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
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.
class Test class Test
{ {
public static void public static void
main(String[] args){ main(String[] args){
System.out.println(10/0); throw new
}} ArithmeticException("/
by zero");
In this case creation of }}
ArithmeticException object and In this case we are creating
handover to the jvm will be exception object explicitly
performed automatically by the and handover to the JVM
main() method. manually.
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:
class Test3 class Test3
{ {
static ArithmeticException static ArithmeticException
e=new e;
ArithmeticException(); public static void
public static void main(String[] args){
main(String[] args){ throw e;
throw e; }
} }
} Output:
Output: Exception in thread "main"
Runtime exception: java.lang.NullPointerExcept
Exception in thread "main" ion
java.lang.ArithmeticExcept at
ion Test3.main(Test3.java:5)
Case 2:
After throw statement we can't take any
statement directly otherwise we will get
compile time error saying unreachable
statement.
Example:
class Test3 class Test3
{ {
public static void public static void
main(String[] args){ main(String[] args){
System.out.println(10/0); throw new
System.out.println("hello") ArithmeticException("/ by
; zero");
} System.out.println("hello
} ");
Output: }
Runtime error: Exception in }
thread "main" Output:
Compile time error.
java.lang.ArithmeticExcepti Test3.java:5: unreachable
on: / by zero statement
at System.out.println("hello
Test3.main(Test3.java:4) ");
Case 3:
We can use throw keyword only for Throwable
types otherwise we will get compile time error
saying incomputable types.
Example:
class Test3
class Test3 extends
{
RuntimeException
public static void
{
main(String[] args){
public static void
throw new Test3();
main(String[] args){
}
throw new Test3();
}Output:
}
Compile time error.
}
Test3.java:4:
Output:
incompatible types
Runtime error: Exception in
found : Test3
thread "main" Test3
required:
at
java.lang.Throwable
Test3.main(Test3.java:4)
throw new Test3();
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){
PrinteWriter 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:
By using try catch By using throws keyword
We can use throws keyword to
delicate the responsibility of
class Test3 exception handling to the caller
{ method. Then caller method is
public static void
main(String[] args){ responsible to handle that
try{ exception.
Thread.sleep(5000); class Test3
} {
catch(InterruptedException public static void
e){} main(String[] args)throws
}
} InterruptedException{
Output: Thread.sleep(5000);
Compile and running }
successfully }
Output:
Compile and running
successfully
Note :
Hence the main objective of "throws"
keyword is to delicate the responsibility of
exception handling to the caller method.
"throws" keyword required only checked
exceptions. Usage of throws for
unchecked exception there is no use.
"throws" keyword required only to
convenes complier. Usage of throws
keyword doesn't prevent abnormal
termination of the program.
Hence recommended to use try-catch over
throws keyword.
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:
we can use throws keyword only for
Throwable types otherwise we will get compile
time error saying incompatible types.
Example:
class Test3{ class Test3 extends
public static void RuntimeException{
main(String[] args) public static void
main(String[] args)
throws Test3
{}
}
Output:
Compile time error throws Test3
Test3.java:2: incompatible {}
types }
found : Test3 Output:
required: Compile and running
java.lang.Throwable successfully.
public static void
main(String[] args)
throws Test3
Case 2: Example:
class Test3{
public static void class Test3{
main(String[] args){ public static void
throw new Exception(); main(String[] args){
} throw new Error();
} }
Output: }
Compile time error. Output:
Test3.java:3: unreported Runtime error
exception Exception in thread "main"
java.lang.Error
java.lang.Exception; at
must be caught or Test3.main(Test3.java:3)
declared to be thrown
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:
1)E:\scjp>java CustomizedExceptionDemo
61
Exception in thread "main"
TooYoungException:
please wait some more time.... u will
get best match
at
CustomizedExceptionDemo.main(CustomizedE
xceptionDemo.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(CustomizedE
xceptionDemo.java:25)
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. ArrayIndexOutOfBoundsException:
It is the child class of RuntimeException
and hence it is unchecked. Raised
automatically by the JVM whenever we
are trying to access array element with out
of range index. Example:
2. class Test{
3. public static void main(String[]
args){
4. int[] x=new int[10];
5. System.out.println(x[0]);//valid
6. System.out.println(x[100]);//AIOOBE
7. System.out.println(x[-100]);//
AIOOBE
8. }
9. }
10. NullPointerException:
It is the child class of RuntimeException
and hence it is unchecked. Raised
automatically by the JVM, whenever we
are trying to call any method on null.
11.Example:
12.class Test{
13.public static void main(String[]
args){
14.String s=null;
15.System.out.println(s.length());
//R.E: NullPointerException
16.}
17.}
18. StackOverFlowError:
It is the child class of Error and hence it is
unchecked. Whenever we are trying to
invoke recursive method call JVM will
raise StackOverFloeError automatically.
19.Example:
20.class Test
21.{
22.public static void methodOne()
23.{
24.methodTwo();
25.}
26.public static void methodTwo()
27.{
28.methodOne();
29.}
30.public static void main(String[]
args)
31.{
32.methodOne();
33.}
34.}
35.Output:
36.Run time error: StackOverFloeError
37. NoClassDefFound:
It is the child class of Error and hence it is
unchecked. JVM will raise this error
automatically whenever it is unable to find
required .class file. Example: java Test
If Test.class is not available. Then we will
get NoClassDefFound error.
38. ClassCastException:
It is the child class of RuntimeException
and hence it is unchecked. Raised
automatically by the JVM whenever we
are trying to type cast parent object to
child type.
Example:
39. ExceptionInInitializerError:
It is the child class of Error and it is
unchecked. Raised automatically by the
JVM, if any exception occurs while
performing static variable initialization
and static block execution.
40.Example 1:
41.class Test{
42.static int i=10/0;
43.}
44.Output:
45.Runtime exception:
46. Exception in thread "main"
java.lang.ExceptionInInitializerErro
r
47.Example 2:
48.class Test{
49.static {
50.String s=null;
51.System.out.println(s.length());
52.}}
53.Output:
54.Runtime exception:
55.Exception in thread "main"
java.lang.ExceptionInInitializerErro
r
56. IllegalArgumentException:
It is the child class of RuntimeException
and hence it is unchecked. Raised
explicitly by the programmer (or) by the
API developer to indicate that a method
has been invoked with inappropriate
argument.
Example:
class Test{
public static void main(String[]
args){
Thread t=new Thread();
t.setPriority(10);//valid
t.setPriority(100);//invalid
}}
Output:
Runtime exception
Exception in thread "main"
java.lang.IllegalArgumentException.
57. NumberFormatException:
It is the child class of
IllegalArgumentException and hence is
unchecked. Raised explicitly by the
programmer or by the API developer to
indicate that we are attempting to convert
string to the number. But the string is not
properly formatted.
Example:
class Test{
public static void main(String[]
args){
int i=Integer.parseInt("10");
int j=Integer.parseInt("ten");
}}
Output:
Runtime Exception
Exception in thread "main"
java.lang.NumberFormatException: For
input string: "ten"
58. IllegalStateException:
It is the child class of RuntimeException
and hence it is unchecked. Raised
explicitly by the programmer or by the
API developer to indicate that a method
has been invoked at inappropriate time.
Example:
Once session expires we can't call any
method on the session object otherwise we
will get IllegalStateException
HttpSession
session=req.getSession();
System.out.println(session.getId());
session.invalidate();
System.out.println(session.getId());
// illgalstateException
59. AssertionError:
It is the child class of Error and hence it is
unchecked. Raised explicitly by the
programmer or by API developer to
indicate that Assert statement fails.
Example:
assert(false);
Exception/Error Raised by
1. AIOOBE
2. NPE(NullPointerException) Raised
3. StackOverFlowError automatically by
4. NoClassDefFoundError JVM(JVM
5. CCE(ClassCastException) Exceptions)
6. ExceptionInInitializerError
Raised explicitly
1. IAE(IllegalArgumentException) either by
2. NFE(NumberFormatException) programmer or by
3. ISE(IllegalStateException) API developer
4. AE(AssertionError) (Programatic
Exceptions).
1.7 Version Enhansements :
As part of 1.7 version
enhansements in Exception
Handling the following 2
concepts introduced
1. try with resources
2. multi catch block
try with resources
Untill 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();
}
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.
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
BACK