|
Flow Control and Exception
Handling
Write
code that makes proper use of exceptions and exception
handling clauses (try, catch, finally) and declares
methods and overriding methods that throw exceptions.
An exception is an
abnormal condition that arises in a code-sequence at
runtime. A Java exception is an object that describes
an exceptional 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 time, the exception is
caught and processed. Exceptions thrown by the java
runtime system relate to fundamental errors that
violate the rules of 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 the method.
Program statements that
are monitored for exceptions are contained within a ‘try’ block. An exception thrown
from the ‘try’ block is
caught, using ‘catch’
block and handled in some rational way. System
generated exceptions are automatically thrown by the
Java runtime 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
provides a powerful mechanism for controlling complex
programs that have many dynamic runtime
characteristics. It is important to think of
try,
catch and
throw as clean ways to
handle errors and unusual boundary conditions in your
program’s logic. Whenever a method can fail, have it
throw an exception.
Java’s exception
handling statements should not be considered a general
mechanism for non-local branching. If you do so, it
will only confuse your code and make it hard to
maintain.
Types of Exception :
All exception types are
subclasses of the class Throwable. Immediately below
Throwable are two subclasses that partition exceptions
into two distinct branches. One branch is headed by
Exception. This class is used for exceptional
conditions that user programs should
catch. This is also the
class that you will subclass to create your own custom
exception types. There is an important subclass of
Exception, called 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.
The other branch is
topped by Error, which defines exceptions that are not
expected to be caught under normal circumstances by
your programs. Exceptions of type Error are used by
Java runtime system to indicate errors having to do
with the runtime environment itself. Stack overflow is
an example of such an error.
Uncaught exceptions:
Whenever an exception
object is created and thrown by the runtime system,
execution of the program stops, because once an
exception has been thrown, it must be caught by an
exception handler and dealt with immediately. If you
do not supply any exception handlers, the exception is
caught by the default handler provided by the Java
runtime system.
The default handler
displays a string describing the exception, prints a
stack-trace from the point at which the exception has
occurred, and terminates the program. The stack trace
will always show the sequence of method invocations
that led up to the error.
Effect on a thread
If an
exception is thrown and it is not handled, the
execution jumps to the end of the current method. The
exception then appears in the caller of that method,
and execution jumps to the end of the calling method.
This continues until execution reaches the top
of the affected thread, at which point the thread
dies.
‘try’ and ‘catch’
The default exception
handler in JVM is useful for debugging. It is best to
handle the exceptions yourself. Doing so provides two
benefits. First, it allows you to fix the error.
Second, it prevents the program from automatically
terminating.
Once an exception is
thrown, the program control transfers out of the ‘try’ block into the ‘catch’ block. Catch block is
not called, so execution never returns to the
try block from
catch. Once the
catch statement has
executed, program control continues with the next line
in the program following the entire
try/catch block.
A
try and its catch
statement form a unit. The scope of
catch clause is
restricted to those statements specified by the
immediately preceding try
block. 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 enclosed within
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 blocks
should be to resolve the exceptional condition and
then continue as if the error had never happened.
Multiple catch clauses:
In some cases, more than
one exception could be raised by a single piece of
code. To handle this type of situation, you can
specify two or more catch
blocks, 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.
When you use multiple
catch blocks, 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.
Nested try statements:
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 runtime system will
handle the exception.
Nesting of
try statements can occur
in less obvious ways when method calls are involved.
You can enclose a call to a method within a
try block. Inside that
method is another try
statement. In this case, the try
statement within the method is still nested inside the
outer try block, which
calls the method.
Displaying a description
of an exception
Throwable overrides the
toString() so that it returns a string containing a
description of the exception. You can display this
description in a println() statement by simply passing
the exception as an argument.
finally
when exceptions are
thrown, execution in a method takes a rather abrupt,
non-linear path that alters the normal flow through
the method. Depending upon how the method is coded, it
is even 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, you will not want the
code that closes the file to be bypassed by the
exception-handling mechanism. The ‘finally’ clause creates a block
of code that will be executed 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 them before returning. The ‘finally’ clause is optional.
However, each try
statement requires at least one
catch or a finally
clause.
If an
exception arises with a matching
catch block, then the
finally block is executed after the
catch block. If no
exception arises, the finally
block is executed after the try
block. If an exception arises for which there is no
catch block, then the
finally block is executed
after the try block.
The
circumstances that can prevent execution of
finally block are :
Any
exception arising in the finally
block can be handled via a try-catch. If no
catch is found then
control jumps out of the method from the point at
which the exception is raised, perhaps leaving the
finally block
incompletely executed.
Catching multiple exceptions
A
catch block handles
exceptions of the class specified in its definition,
as well as exceptions that are subclasses of the one
specified. If you wish to catch multiple exceptions
which are related to each other by super class/ sub
class relation, then the following points should be
kept in mind :
-
The
catch block specifying
super class must come after the
catch block which
intends to catch the sub class.
-
Out
of many catch blocks,
you might have defined, only one
catch block, which is
the first applicable one, will be executed.
If
exceptions are not related by super-sub relation then
the order of catch blocks
is not important.
The throw statement
It is possible for a
program to throw an exception explicitly using the ‘throw’ statement (e.g. throw
object;). The object to be thrown must of type
Throwable or a subclass of it. Simple types such as
int or
char as well as
non-Throwable classes, such as String or Object,
cannot be used as exceptions. There are two ways you
can obtain a Throwable object: using a parameter into
a catch clause or
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’
statement 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, the next enclosing try
statement is inspected and so on. If no matching
catch block is found,
then default exception handler halts the program and
prints the stack trace.
All of Java’s built in
runtime exceptions have two constructors: one with no
parameters and one that takes a String parameter. When
the second form is used, the argument specifies a
string that describes the exception. This string is
displayed when the object is used as an argument to
print() or println(). It can also be obtained by a
call to getMessage(), which is defined by Throwable.
A
throw statement should be
conditional in some way so that it has a way to
complete successfully.
The throws statement
If a
method is capable of causing an exception that it does
not handle itself, it must specify this behavior so
that the callers of the method can guard themselves
against that exception. It can be done 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. If a
method declares that it throws more than one
exception, class hierarchy of exceptions is important
in the declaration - subclass coming before a super
class.
Checked exceptions
The
checked exceptions are problems that can arise in a
correct program. These are concerned with difficulties
with the environment such as user mistakes or I/O
problems. Since these conditions can arise at anytime,
a program must be able to handle and recover from
them. The compiler checks whether a program has
defined what is to be done when such conditions arise.
Exceptions and Overriding
A
method which overrides a method in a super class can
only be declared to throw checked exceptions of
classes which were either declared to be thrown by the
method in super class or which are subclasses of those
exceptions declared in the method of super class.
This
restriction is because Java allows use of super class
references as references to objects of subclass. If an
overriding method were allowed to throw exceptions of
super class of those declared for the overridden
method, then overriding methods would be able to
bypass the enforced checks for checked exceptions.
Java’s built in
exceptions:
Inside the standard
package java.lang, Java defines several exception
classes. The most general of these are subclasses of
RuntimeException. Since, java.lang is implicitly
imported to all Java programs, most exceptions derived
from RuntimeException are automatically available.
They need not be included in any method’s
throws list. They are
called unchecked exceptions because the compiler does
not check to see if a method handles, or throws these
exceptions. Checked exceptions are those defined by
java.lang 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.
RuntimeException
subclasses (unchecked):
-
ArithmeticException
-
ArrayIndexOutOfBoundsException
-
ArrayStoreException
-
ClassCastException
-
IllegalArgumentException
-
IllegalMonitorStateException
-
IllegalStateException
-
IllegalThreadStateException
-
IndexOutOfBoundsException
-
NegativeArraySizeException
-
NullPointerException
-
NumberFormatException
-
SecurityException
-
StringIndexOutOfBoundsException
-
UnsupportedOperationException
Checked Exceptions
defined in java.lang:
Creating new Exception
subclasses:
Although Java’s built-in
exceptions handle most common errors, you may want to
create your own exception types to handle situations
specific to your applications. To do this, just define
a subclass of Exception. Your subclasses do not need
to implement anything actually – 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 does 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.
Methods defined in
Throwable:
-
Throwable
fillInStackTrace ()
-
String
getLocalizedMessage ()
-
String getMessage ()
-
void printStackTrace
()
-
void printStackTrace
(PrintStream stream)
-
void printStackTrace
(Printwriter stream)
-
String toString ()
section2-1 | section2-2 | section2-3
Sections :
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11
If you wish to download the complete notes
(around 100 pages - pdf or doc file) for a small price, click here. |