Exception-Handling
• An exception is an abnormal condition that arises
in a code sequence at run time.
• In other words, an exception is a run-time error.
• In computer languages that do not support
exception handling, errors must be checked and
handled manually - typically through the use of
error codes, and so on.
• This approach is as cumbersome as it is
troublesome.
Exception-Handling contd..
• A Java exception is an object that describes an
exceptional (that is, error) condition that has
occurred in a piece of code.
• When an exceptional condition arises, an object
representing that exception is created and thrown
in the method that caused the error.
• That method may choose to handle the exception
itself, or pass it on.
• Either way, at some point, the exception is
caught and processed.
Exception-Handling contd..
• Exceptions can be generated by
1. Java run-time system
2. be manually generated by your code.
• Exceptions thrown by Java relate to fundamental
errors that violate the rules of the Java language
or the constraints of the Java execution
environment.
• Manually generated exceptions are typically used
to report some error condition to the caller of a
method
Exception-Handling contd..
• Java exception handling is managed via five
keywords:
1. try
2. catch
3. throw
4. throws
5. finally
• Program statements that you want to monitor for
exceptions are contained within a try block.
• If an exception occurs within the try block, it is
thrown.
• Your code can catch this exception (using catch)
and handle it in some rational manner.
Exception-Handling contd..
• System-generated exceptions are
automatically thrown by the Java run-time
system.
• To manually throw an exception, use the
keyword throw.
• Any exception that is thrown out of a method
must be specified as such by a throws
clause.
• Any code that absolutely must be executed
before a method returns is put in a finally
block.
Exception-Handling contd..
This is the general form of an exception-handling block:
try
{
// block of code to monitor for errors
}
catch (ExceptionType1 exOb)
{
// exception handler for ExceptionType1
}
catch (ExceptionType2 exOb)
{
// exception handler for ExceptionType2
}
// ...
finally
{
// block of code to be executed before try block ends
}
Here, ExceptionType is the type of exception that has occurred.
Exception Types
Throwable
Exception Error
RuntimeException
• Exceptionis used for exceptional conditions that
user programs should
• catch. This is also the class that you will subclass
to create your own custom exceptiontypes.
• RuntimeException. Exceptions of this type are
automatically defined for the programs that you
write and include things such as division by zero
and invalid array indexing.
Exception Types
• Error defines exceptions that are not expected to
be caught under normal circumstances by your
program.
• Exceptions of type Error are used by the Java
run-time system to indicate errors having to do
with the run-time environment, itself. Stack
overflow is an example of such an error.
• These are typically created in response to
catastrophic failures that cannot usually be
handled by your program.
Uncaught Exceptions
• causes a divide-by-zero error.
class Exc0 {
public static void main(String args[]) {
int d = 0;
int a = 42 / d;
}
}
• When the Java run-time system detects the
attempt to divide by zero, it constructs a new
exception object and then throws this exception.
This causes the execution of Exc0 to stop
• Because once an exception has been thrown, it
must be caught by an exception handler and dealt
with immediately.
• In this example, we haven’t supplied any
exception handlers of our own, so the exception
is caught by the default handler provided by the
Java run-time system.
• Any exception that is not caught by your
program will ultimately be processed by the
default handler.
• The default handler displays a string describing
the exception, prints a stack trace from the point
at which the exception occurred, and terminates
the program.
• Here is the output generated when this example is executed.
[Link]: / by zero
at [Link]([Link])
• class name, Exc0
• method name, main;
• filename, [Link];
• line number, 4, are all included in the simple stack trace.
• Type of the exception thrown is a subclass of Exception
called ArithmeticException,
• which more specifically describes what type of error
happened.
• Java supplies several built-in exception types that match the
various sorts of run-time errors that can be generated.
• The stack trace will always show the sequence of method
invocations that led up to the error.
• same error but in a method separate from main( ):
class Exc1 {
static void subroutine() {
int d = 0;
int a = 10 / d;
}
public static void main(String args[]) {
[Link]();
}
}
• The resulting stack trace from the default exception handler
shows how the entire call stack is displayed:
[Link]: / by zero
at [Link]([Link])
at [Link]([Link])
• As you can see, the bottom of the stack is main’s line 7,
which is the call to subroutine( ), which caused the
exception at line 4.
• The call stack is quite useful for debugging, because it
pinpoints the precise sequence of steps that led to the error.
Using try and catch
• usually want to handle an exception yourself.
• Doing so provides two benefits.
1. it allows you to fix the error.
2. it prevents the program from automatically
terminating.
• To guard against and handle a run-time error,
simply enclose the code that you want to monitor
inside a try block.
• Immediately following the try block, include a
catch clause that specifies the exception type
that you wish to catch.
class Exc2
{
public static void main(String args[])
{
int d, a;
try
{ // monitor a block of code.
d = 0;
a = 42 / d;
[Link]("This will not be
printed.");
}
catch (ArithmeticException e)
{ // catch divide-by-zero error
[Link]("Division by zero.");
}
[Link]("After catch statement.");
}
}
• This program generates the following output:
Division by zero.
• Once anexception is thrown, program
control transfers out of the try block into the
catch block.
• execution never “returns” to the try block
from a catch.
• Once the catch statement has executed,
program control continues with the next line
in the program following the entire try/catch
mechanism.
• A try and its catch statement form a unit.
• The scope of the catch clause is restricted to those
statements specified by the immediately preceding try
statement.
• A catch statement cannot catch an exception thrown by
another try statement (except in the case of nested try
statements).
• The statements that are protected by try must be
surrounded by curly braces. (That is, they must be
within a block.)
• You cannot use try on a single statement.
• The goal of most well-constructed catch clauses should
be to resolve the exceptional condition and then
continue on as if the error had never happened.
Displaying a Description of an Exception
catch (ArithmeticException e)
{
[Link]("Exception: " + e);
a = 0; // set a to zero and continue
}
• When this version is substituted in the program,
and the program is run, each divide-by-zero error
displays the following message:
Exception: [Link]: / by zero
• Which is useful when you are experimenting
with exceptions or when you are debugging.
Multiple Catch Clauses
• you can specify two or more catch clauses, each
catching a different type of exception.
• When an exception is thrown, each catch
statement is inspected in order, and the first one
whose type matches that of the exception is
executed.
• After one catch statement executes, the others
are bypassed, and execution continues after the
try/catch block
// Demonstrate multiple catch statements.
class MultiCatch
{
public static void main(String args[])
{
try
{
int a = [Link];
[Link]("a = " + a);
int b = 42 / a;
int c[] = { 1 };
c[42] = 99;
}
catch(ArithmeticException e)
{
[Link]("Divide by 0: " + e);
}
catch(ArrayIndexOutOfBoundsException e)
{
[Link]("Array index oob: " + e);
}
[Link]("After try/catch blocks.");
}
}
Multiple Catch Clauses
• This program will cause a division-by-zero exception if it is
started with no commandline parameters, since a will equal zero.
• It will survive the division if you provide a command-line
argument, setting a to something larger than zero.
• But it will cause an ArrayIndexOutOfBoundsException, since
the int array c has a length of 1, yet the program attempts to
assign a value to c[42].
• Here is the output generated by running it both ways:
C:\>java MultiCatch
a=0
Divide by 0: [Link]: / by zero
After try/catch blocks.
C:\>java MultiCatch TestArg
a=1
Array index oob: [Link]
After try/catch blocks.
• When you use multiple catch statements, it
is important to remember that exception
subclasses must come before any of their
superclasses.
• This is because a catch statement that uses
a superclass will catch exceptions of that
type plus any of its subclasses. Thus, a
subclass would never be reached if it came
after its superclass.
• Further, in Java, unreachable code is an
error.
/* This program contains an error. A subclass must come before its superclass in a
series of catch statements. If not,unreachable code will be created and a
compile-time error will result.*/
class SuperSubCatch
{
public static void main(String args[])
{
try
{
int a = 0;
int b = 42 / a;
}
catch(Exception e)
{
[Link]("Generic Exception catch.");
}
/* This catch is never reached because
ArithmeticException is a subclass of Exception. */
catch(ArithmeticException e)
{ // ERROR - unreachable
[Link]("This is never reached.");
}
}
}
• If you try to compile this program, you will
receive an error message stating that the
second catch statement is unreachable
because the exception has already been
caught.
• To fix the problem, reverse the order of the
catch statements.
Nested try statements
• The try statement can be nested.
• That is, a try statement can be inside the block of
another try.
• Each time a try statement is entered, the context of that
exception is pushed on the stack.
• If an inner try statement does not have a catch handler
for a particular exception, the stack is unwound and the
next try statement’s catch handlers are inspected for a
match.
• This continues until one of the catch statements
succeeds, or until all of the nested try statements are
exhausted.
• If no catch statement matches, then the Java run-time
system will handle the exception.
// An example of nested try statements.
class NestTry
{
public static void main(String args[])
{
try
{
int a = [Link];
/* If no command-line args are present, the following statement will generatea divide-by-zero
exception. */
int b = 42 / a;
[Link]("a = " + a);
try
{ // nested try block
/* If one command-line arg is used, then divide-by-zero exception will be generated by the
following code. */
if(a==1) a = a/(a-a); // division by zero
/* If two command-line args are used, then generate an out-of-bounds exception. */
if(a==2)
{
int c[] = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
}
catch(ArrayIndexOutOfBoundsException e)
{
[Link]("Array index out-of-bounds: " + e);
}
}
catch(ArithmeticException e)
{
[Link]("Divide by 0: " + e);
}
}
}
C:\>java NestTry
Divide by 0: [Link]: / by zero
C:\>java NestTry One
a=1
Divide by 0: [Link]: / by zero
C:\>java NestTry One Two
a=2
Array index out-of-bounds:
[Link]
• you can enclose a call to a method within a try block.
• Inside that method is another try statement. In this case, the try
within the method is still nested inside the outer try block, which
calls the method.
/* Try statements can be implicitly nested via calls to methods. */
class MethNestTry
{
static void nesttry(int a)
{
try
{ // nested try block
/* If one command-line arg is used, then a divide-by-zero exception will be generated by the
following code. */
if(a==1) a = a/(a-a); // division by zero
/* If two command-line args are used, then generate an out-of-bounds exception. */
if(a==2)
{
int c[] = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
}
catch(ArrayIndexOutOfBoundsException e)
{
[Link]("Array index out-of-bounds: " + e);
}
}
public static void main(String args[])
{
try
{
int a = [Link];
/* If no command-line args are present,the following statement will generatea divide-by-zero exception. */
int b = 42 / a;
[Link]("a = " + a);
nesttry(a);
}
catch(ArithmeticException e) {
[Link]("Divide by 0: " + e);
}
}
}
The output of this program is identical to that of the preceding example.
throw
• it is possible for your program to throw an
exception explicitly, using the throw statement.
• The general form of throw is shown here:
throw ThrowableInstance;
• Here, ThrowableInstance must be an object of
type Throwable or a subclass of Throwable.
• Simple types, such as int or char, as well as
non-Throwable classes, such as String and
Object, cannot be used as exceptions.
• There are two ways you can obtain a Throwable object:
1. using a parameter into a catch clause
2. creating one with the new operator.
• The flow of execution stops immediately after the
throw statement; any subsequent statements are not
executed.
• The nearest enclosing try block is inspected to see if it
has a catch statement that matches the type of the
exception. If it does find a match, control is transferred
to that statement.
• If not, then the next enclosing try statement is
inspected, and so on.
• If no matching catch is found, then the default
exception handler halts the program and prints the stack
trace.
// Demonstrate throw.
class ThrowDemo
{
static void demoproc()
{
try
{
throw new NullPointerException("demo");
}
catch(NullPointerException e)
{
[Link]("Caught inside demoproc.");
throw e; // rethrow the exception
}
}
public static void main(String args[])
{
try
{
demoproc();
}
catch(NullPointerException e)
{
[Link]("Recaught: " + e);
}
}
}
resulting output:
Caught inside demoproc.
Recaught: [Link]: demo
throws
• If a method is capable of causing an exception that it
does not handle, it must specify this behavior so that
callers of the method can guard themselves against that
exception.
• You do this by including a throws clause in the
method’s declaration.
• A throws clause lists the types of exceptions that a
method might throw.
• This is necessary for all exceptions, except those of type
Error or RuntimeException, or any of their
subclasses.
• All other exceptions that a method can throw must be
declared in the throws clause.
• If they are not, a compile-time error will result.
• general form of a method declaration that
includes a throws clause:
type method-name(parameter-list) throws exception-list
{
// body of method
}
• Here, exception-list is a comma-separated list of
the exceptions that a method can throw.
// This program contains an error and will not compile.
class ThrowsDemo
{
static void throwOne()
{
[Link]("Inside throwOne.");
throw new IllegalAccessException("demo");
}
public static void main(String args[])
{
throwOne();
}
}
To make last example compile, you need to make two changes.
1. you need to declare that throwOne( ) throws IllegalAccessException.
2. Second, main( ) must define a try/catch statement that catches this exception.
// This is now correct.
class ThrowsDemo
{
static void throwOne() throws IllegalAccessException
{
[Link]("Inside throwOne.");
throw new IllegalAccessException("demo");
}
public static void main(String args[])
{
try
{
throwOne();
}
catch (IllegalAccessException e)
{
[Link]("Caught " + e);
}
}
}
Output:
inside throwOne
caught [Link]: demo
finally
• It is possible for an exception to cause the method to
return prematurely. This could be a problem in some
methods.
• For example, if a method opens a file upon entry and
closes it upon exit, then you will not want the code that
closes the file to be bypassed by the exception-handling
mechanism.
• The finally keyword is designed to address this
contingency.
• finally creates a block of code that will be executed
after a try/catch block has completed and before the
code following the try/catch block.
• The finally block will execute whether or not an
exception is thrown.
• If an exception is thrown, the finally block will execute
even if no catch statement matches the exception.
• Any time a method is about to return to the
caller from inside a try/catch block, via an
uncaught exception or an explicit return
statement, the finally clause is also executed
just before the method returns.
• This can be useful for closing file handles and
freeing up any other resources that might have
been allocated at the beginning of a method
with the intent of disposing of them before
returning.
• The finally clause is optional. However, each
try statement requires at least one catch or a
finally clause.
// Demonstrate finally. // Execute a try block normally.
class FinallyDemo static void procC()
{ {
// Through an exception out of the method. try
static void procA() {
{ [Link]("inside procC");
try }
{ finally
[Link]("inside procA"); {
throw new [Link]("procC's finally");
RuntimeException("demo"); }
} }
finally public static void main(String args[])
{ {
[Link]("procA's finally"); try
} {
} procA();
// Return from within a try block. }
static void procB() catch (Exception e)
{ {
try [Link]("Exception
{ caught");
[Link]("inside procB"); }
return; procB();
} procC();
finally }
{ }
[Link]("procB's Output:
finally");
} inside procA
} procA’s finally
Exception caught
inside procB
procB’s finally
inside procC
procC’s finally
If a finally block is associated with a try,
the finally block will be executed upon
conclusion of the try.
Java’s Built-in Exceptions
• Inside the standard package [Link], Java defines
several exception classes.
• The most general of these exceptions are subclasses of
the standard type RuntimeException.
• They need not be included in any method’s throws list.
• In the language of Java, these are called unchecked
exceptions because the compiler does not check to see
if a method handles or throws these exceptions.
• Some exceptions defined by [Link] that must be
included in a method’s throws list if that method can
generate one of these exceptions and does not handle it
itself.
• These are called checked exceptions.
• Java defines several other types of exceptions that
relate to its various class libraries.
Checked Exceptions
• Compile-time Check: Checked exceptions are checked at
compile-time by the Java compiler. This means that the
compiler ensures that these exceptions are either caught or
declared in the method signature using the throws keyword.
• Examples: Examples of checked exceptions include
IOException, SQLException, ParseException, etc.
• Forced Handling: Checked exceptions enforce explicit
handling, either by catching them or declaring them to be
thrown. This helps in improving code reliability and
robustness.
• Recovery Possible: Checked exceptions typically represent
recoverable conditions, such as file not found or database
connection failure, where the application may take corrective
action.
Unchecked Exceptions
• Not Checked at Compile-time: Unlike checked exceptions,
unchecked exceptions are not checked at compile-time. This
means that the compiler does not enforce handling of
unchecked exceptions.
• Examples: Examples of unchecked exceptions include
NullPointerException, ArrayIndexOutOfBoundsException,
ArithmeticException, etc.
• Runtime Errors: Unchecked exceptions often represent
programming errors or unexpected conditions during
runtime, such as null references or array index out of
bounds.
• Optional Handling: Handling of unchecked exceptions is
optional. While it's good practice to handle them for
robustness, it's not mandatory.
Creating Your Own Exception Subclasses
• We can create your own exception types to handle
situations specific to your applications.
• just define a subclass of Exception (which is, of course,
a subclass of Throwable).
• Your subclasses don’t need to actually implement
anything—it is their existence in the type system that
allows you to use them as exceptions.
• The Exception class does not define any methods of its
own. It inherit those methods provided by Throwable.
• Thus, all exceptions, including those that you create,
have the methods defined by Throwable available to
them.
• You may also wish to override one or more of these
methods in exception classes that you create.
// This program creates a custom exception type.
class MyException extends Exception
{
private int detail;
MyException(int a)
{
detail = a;
}
public String toString()
{
return "MyException[" + detail + "]";
}
}
class ExceptionDemo
{
static void compute(int a) throws MyException
{
[Link]("Called compute(" + a + ")");
if(a > 10)
throw new MyException(a);
[Link]("Normal exit");
}
public static void main(String args[])
{
try
{
compute(1);
compute(20);
}
catch (MyException e)
{
[Link]("Caught " + e);
}
}
}
result:
Called compute(1)
Normal exit
Called compute(20)
Caught MyException[20]
Advantages of Exception
• Provision to Complete Program Execution
• Easy Identification of Program Code and Error-
Handling Code
• Propagation of Errors
• Meaningful Error Reporting
• Identifying Error Types