You are on page 1of 23

Saint Paul Institute

Chapter 8: Exceptions and


Assertions
Objectives
Improve the reliability of code by incorporation
exception-handling and assertion mechanisms.
Write methods that propagate exceptions.
Implement the try-catch blocks for catching and
handling the thrown exceptions.
Write programmer-defined exception classes.
Distinguish between the checked and unchecked, or
runtime, exceptions.
Use assertions in methods to increase the chance of
detecting bugs during the development.
Introduction
When someone says his or her program is reliable,
what do we expect from the program? The majority of
people would probably reply correctness as the most
important criterion in determining the reliability of a
program. When a program is claimed to be reliable, we
certainly expect the program will produce correct
results for all valid input. As we all know by now,
writing a correct program is easier said than done. If
we are not diligent and carful enough, we can easily
introduce bugs in our programs.
And often we fail to eradicate them. A mechanism
called an assertion, a new feature from Java 2 SDK 1.4,
can be used to improve the likelihood of catching
logical errors during the development. We will
introduce assertions in this chapter and show how to
use them effectively in our programs.
Program correctness guarantees correct results for all
valid input. But what happens when the input is
invalid? A mechanism called exception handling can
be used to improve the program’s robustness.
8.1 Catching Exceptions
The exception-handling mechanism can be viewed as
another from of control structure. An exception
represents an error condition that can occur during the
normal course of program execution. When an
exception occurs, the normal sequence of flow is
terminated and the exception-handling routine is
executed. For example, consider this code:
String inputStr =JoptionPane.showInputDialog(null, “ ”);
int number = Integer.parseInt(inputStr);
What would happen if we entered “abc123”?
Chapter8 Sample Program code!
try-catch control statement:

inputStr = JOptionPane.showInputDialog(null,
prompt);
try {
int age = Integer.parseInt(inputStr);

} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, “ ‘ “+
inputStr + “ ‘ is invalid\n” + “Please enter
digits only”);
}
public int getAge (String prompt) {
String inputStr; This statement is executed only
if no exception is thrown by
int age; parselnt.
boolean keepGoing = true;
while (keepGoing) {
inputStr = JOptionPane.showInputDialog (null, prompt);
try {
age = Integer.parseInt (inputStr);
keepGoing = false; //input okay so stop looping
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog (null, “’” + inputStr + “’ is
invalid\n” + “Please enter digits only”);
} } return age; }
8.2 Throwing Exceptions and Multiple catch
Blocks
Compared to the original AgeInputVer1 class, the
AgeInputVer2 class is more robust because the
program does not terminate abruptly when an invalid
value is entered. However, the improved class is not
robust enough yet. There is still room for
improvements. For example, the current
implementation accepts invalid negative integers.
Since negative age is not possible, let’s improve the
code to take care of the invalid input of negative
integers.
Notice that a negative integer is an integer, so the
parseInt method will not throw an exception. We will
define the third class, AgeInputVer3, to throw (and
catch) an exception when the invalid input of a
negative integer is detected. Here’s the while loop of
the modified getAge method of the AgeInputVer3
class.
whle (true) {
inputStr = JOptionPane.showInputDialog(null, prompt);
try { age = Integer.parseInt(inputStr);
if (age < 0) { throw new Exception (“Nagative age is
invalide”);
} return age; //input OK so return the value & exit
} catch (NumberFormat Exception e) {
JOptionPane.showMessagedialog(null, “ ’ ” +
inputStr + “ ‘ is invalid\n” + Please enter digits
only”); } catch (Exception e) {
JOptionPane.showMessageDialog(null, “Error:” +
e.getMessage () ); } }
Exception No exception
Assume <t-stmt-3> throws an exception
and <catch-block-3> is the matching
catch block

try { try {
<t-stmt-1> <t-stmt-1>
<t-stmt-2> <t-stmt-2>
<t-stmt-3> <t-stmt-3>
<t-stmt-4> <t-stmt-4>
… …
<t-stmt-n> <t-stmt-n>
} }
<catch-block-1> <catch-block-1>
<catch-block-2> <catch-block-2>
<catch-block-3> <catch-block-3>
<catch-block-4> <catch-block-4>
… …
<catch-block-5> <catch-block-5>

<next stmt> <next stmt>


8.3 Propagating Exceptions
When a method may throw an exception, either
directly by including a throw statement or indirectly
by calling a method that throws an exception, we call
the method an exception thrower. Every exception
thrower must one of the two types: catcher or
propagator. An exception catcher is an exception
thrower that includes a matching catch block for the
thrown exception, while an exception propagator does
not.
Method A Method B Method C Method D
Try { Try {
B (); C ();
} catch (Exception e) } catch (Exception e) if (cond) { throw new
D ();
{ { Exception (); }
output.println(“A”); output.println(“B”);
} }

Call sequence
Method A Method B Method C Method D
Catcher Propagator Propagator

Stack trace

D
C C
B B B
A A A A
Method A calls method B, method B in turn calls method
C, and so forth. Notice the stack trace in the figure.
Every time a method is executed, the method’s name is
placed on top of the stack. By the time method D is
executed, we have A, B, C, and D in the stack. When an
exception is thrown, the system searches down the
stack from the top, looking for the first matching
exception catcher. Method D throws an exception, but
no matching catch block exists in the method, so
method D is an exception propagator. The system then
checks method C. This Method is also an exception
propagator. Finally, the system locates the matching
catch block in method B, and therefore, method B is
the catcher for the exception thrown by method D.
Method A also includes the matching catch block, but
it will not be executed because the thrown exception is
already caught by method B, and method B does not
propagate this exception. Although the techique is not
used often, an exception catcher can also be set to
propagate the caught exception. For example, if we
rewrite method B as:
try {
C ();
} catch (Exception e) {………. //do something here
throw e; // propagate the caught exception to the
//method below this one in the trace stack
}
it is both a catcher and propagator. With modified
method B, method A’s matching catch block will get
executed, because method B, in addition to handling
the exception, throws the same exception, causing the
system to look for a matching catcher down the stack.
We have one last detail to complete the description of
the exception propagation mechanism. If a method is
an exception propagator, we need to modify its word
throws for this type of exceptions the method
propagators. We use the reserved word throws for
declaration. Methods C and D must have the follwing
declaration:
void C () throws Exception { …………….}
void D() throws Exception { …………….}
AgeInputVer4.java
8.4 Types of Exceptions
There are two types of exceptions: checked and
unchecked. A checked exception is an exception that is
checked at compile time. All other exceptions are
unchecked exceptions, also called runtime exceptions,
because they are unchecked at compile time and are
detected only at runtime.
Caller A (catcher)
Void callerA ( ) {
Try {
doWork ( );
} catch (RuntimeException e) {…….}

Caller B (propagator) doWork throws RuntimeException


Void callerB ( ) throws Public void doWork {
RuntimeException { ……….
……………. throw new
doWork ( ); RuntimeException ();
…………………..} ………………..}

Caller C (propagator)
Void callerC ( ) {
……………. This is the most common style of
doWork ( ); runtime exceptions. Notice that
…………………..} caller C is a propagator implicityly.
8.5 Programmer-Defined Exception
Let’s define a class anmed AgeInputException as a
sebclass of the Exception class. To provide useful
information to the client, we will define the class so
the instances will carry three pieces of information:
lower bound, upper bound, and the value entered by
the user (in addition to the message inherited from the
Exception class). We will define three public methods
to access these data. Here’s the class definition:

AgeInputException.java
8.6 Assertionos
In this section we will describe a Java assertion and
explain how to use it effectively in our programs. A Java
assertion is a language feature we use to detect logical
errors in a program. We will illustrate the key points
with a very simple class that includes a logical error.
Because the sample class is simple, the use of assertion
may not seem so helpful. Keep in mind that this class is
for illustrative purposes only. The real benefit of using
the assertion feature becomes obvious when the
program logic gets more complex and the number of
classes in the program increases.
Here’s a bank account class that allows withdrawals
and deposits. There’s one logical error in the class.
class BankAccount {
private double balance;
public BankAccount (double initialBalance) {
balance = initialBalance;
}
public void deposit (double amount) {
double oldB alance = balance;
balance -= amount; Here’s a logical error. We
should add the amount.
assert balance > oldBalance;
}
public void withdraw (double amount) {
double oldBalance = balance;
balance -= amount;
If this boolean expression
assert balance < oldBalance; result in false, then an
} AssertionError is thrown.

public double getBalance ( ) {


return balance;
}
}
Type of Assertions
The type of assertion we see in the withdraw and
deposit methods is called a postcondition assertion.
This assertion checks for a condition that must be true
after a method is executed. Opposite to the
postcondition assertion is a precondition assertion,
a checking of condition that must be true before a
method is executed. The third type of assertion is
called a control flow invariant.

You might also like