Exceptions   
Peter Komisar   ©  Conestoga College   
latest revision 5.5  /  2008


Exception Hierarchy



"Houston, we have a problem."

Exception handling is a plan for changing a program's
flow of control when an
unexpected event or error
occurs. Control is diverted to a part of the program
which communicates with the user. Exceptions are
thrown by unacceptable
conditions, such as dividing
an integer by zero or trying to access an array
element outside of it's defined bounds.

// Exceptions are thrown by unacceptable conditions arising

Like most everything in Java, exceptions are handled
using an object-based
model. Program problems are
encapsulated in class objects. When an exception

occurs, an Exception object is created, specifically,
one of many specialized
descendants of Throwable,
signaling to the program it has a problem that has to
be handled
.

// Descendants of Throwable are created in response to
// error conditions

The programmer can choose to deal with an exception
using a 'try...catch'
construct or it can pass the exception
on up, (the call stack) all the way to
main( ). If main( )
doesn't handle the exception, the program will halt
with an error report explaining what happened.

// Different tactics may be used in dealing with exceptions
// shown below

The figure below shows the inheritance relationships
that exist between Throwable and
it's descendants.
The tree describes two branches. There is the Error
branch
and the Exception branch.

The Exception branch is subclassed to form the various
checked exceptions. The Exception class is subclassed
by the
RuntimeException exception class which is the
parent of the various runtime
exceptions.


The Throwable Hierarchy

The hierarchy essentially describes three groups of
exceptions.
Errors, runtime exceptions and checked
exceptions. A more detailed diagram
is provided
below the figure. Notice even the detailed diagram
doesn't show
all the exception classes used in the
JDK. There are also special Exception
classes, such
as SQLException, that are defined inside packages
devoted to particular
topics. It makes sense to house
these specialized Exception class types with
the
packages that use them.

// other 'dedicated' Exceptions reside in different packages
 

The Exception Hierarchy

       
Object

|

Throwable / \
Exception Error / \
Checked Runtime
Exceptions
Exceptions


Exception Hierarchy Tree

// Abbr. from JDK  documentation. The Throwable
// hierarchy  is in java.lang package

Object
   |
Throwable
   |
   |__Error
   |__Exception
        |
        |__ClassNotFoundException
        |__CloneNotSupportedException
        |__IllegalAccessException
        |__InstantiationException
        |__InterruptedException
        |__NoSuchFieldException
        |__NoSuchMethodException
        |
        |____RuntimeException
                  |
                  |__ArithmeticException
                  |__ArrayStoreException
                  |__ClassCastException
                  |__IllegalArgumentException
                  |       |__IllegalThreadStateException
                  |       |__NumberFormatException
                  |
                  |__IllegalMonitorStateException
                  |__IllegalStateException
                  |__IndexOutOfBoundsException
                  |      |__ArrayIndexOutOfBoundsException
                  |      |__StringIndexOutOfBoundsException
                  |
                  |__NegativeArraySizeException
                  |__NullPointerException
                  |__SecurityException
                  |__UnsupportedOperationException

 

// The Throwable hierarchy is all in java.lang package 
// Throwable is parent to
Exception and Error. Exception
// class includes checked and runtime exceptions

 


Checked & Runtime Exceptions & Errors



Checked Exceptions 

// expected errors that may happen in a correct program

Checked exceptions arise in a correct program
from problems arising during a program's use. A
user might make a typing error and enter a letter
where a number should be located. A power failure
might cause an interruption in a network socket
connection causing an IOException to be thrown.
These are types of error a programmer can expect
to occur and needs to be ready to handle.

If a situation arises that may cause a checked
exception to be raised but the programmer hasn't
provided some code to handle the exception the
compiler will report the problem to the programmer.
For instance the compiler might report something
like, "java.lang.SomeKindOfException must be
caught or declared to be thrown."  The following
example won't compile. The compiler reports
InterruptedException must be caught.


Example

class CheckEx{
     public static void main(String args[]){
         Thread.sleep(1000);
         }
     }  
 // doesn't compile,
// reports InterruptedException must be caught


Runtime Exceptions  

Runtime exceptions are thrown by what are commonly
called program bugs. A typical example of this is when
a loop incorrectly references an array element that is
beyond the range of defined elements. For example,
an attempt is made to access the tenth array element
in an array that only has nine elements. This will cause
an ArrayOutOfBounds exception to be thrown.

// bugs that show up at runtime need to be fixed by
// the programmer

In a correct program, runtime exceptions should never
occur so you are not required by Java to handle them.
It is assumed the programmer will fix any problems
that cause these runtime exceptions to occur. In the
case of runtime exceptions, they show up and reported
when the program is run.

// Runtime exceptions may be harder to spot
// as the compiler sees the code as being legal

Runtime exceptions are often harder to repair as they
can result from what is correct code from the compilers
point of view. The code is correct in the sense it logical
leads to the result that causes the runtime exception to
be thrown. To show the 'Array Out of Bounds' problem
the following sample compiles fine but at runtime throws
an ArrayOutOfBounds exception. 


Example   

class ArrayBug{
     public static void main(String args[]){
            float [ ]  f={ 1.01f  };
            System.out.println( f[1] );
            }
      }   

// compiles but fails to run. ArrayOutOfBounds exception is thrown

Errors

Errors describe environmental problems which may be
rare or difficult to recover from such as running out of
computer memory. You are not expected to handle
Error class objects. These should be regarded as
environmental flaws. Hopefully you will never need to
deal with them.



User Defined Exceptions & the throw Statement



The 'throw' Keyword

Before we look at the error handling strategies that Java
supplies, we will look at how a programmer can take
control of when an exception is thrown using the keyword
'throw'.

As we know by now, Java is an object-oriented environment.
Even exceptions are defined as classes that are used as
templates to create exception objects. This leads to the
possibility for the Java programmer to use inheritance to
define custom exception classes.

Custom exception classes are created by extending
Exception class. The programmer can use the 'throw'
keyword in conjunction with the given exception class
constructor to generate objects of this class in response
to certain circumstances. Exceptions are thrown implicitly
when something illegal has occurred in a program. In
contrast, exceptions are thrown explicitly with the keyword
'throw' under conditions that the programmer chooses.

// the 'throw' keyword together with object-oriented
// inheritance allows
custom exceptions to be created

In the following example, a custom exeption class called
PartyException is created by extending Exception. This
exception object is thrown, in the BirthdayCalendar call
if some birthday condition is met.

( Note it is not recommended coding practice to use
exception handling as a sort of flow control to do regular
coding. Exception handling is designed to handle to
unexpected or undesirable conditions. We might make
an 'exception' at this point as the following example is
easy to understand and illustrates clearly how 'throw'
works. )

Example

class PartyException extends Exception{
    PartyException( ){
    System.out.println("Time for a party");
    }
   }
// PartyException extends Exception. When it's constructor
// is invoked, "Time for a party" is printed to console

class BirthdayCalendar{
  public static void main(String[] args) throws PartyException {
// to get pass the compiler we show main throwing the exception
// Assume we have a list we loop through, itemizing  family
// birthdays
Also assume the current date (plus some advance
// time) is compared to a list
of birthdates. If one is found, the
// boolean  'a_birthday' is set to true

          
        if (a_birthday)  throw new PartyException( );
         }
      }

The 'throw' keyword is used in conjunction with the 'new'
operator and the constructor of the PartyException class.
The suffix, 'throw PartyException' has been appended to
the main( ) method signature. This is necessary in order
for the code to compile in it's current form. This satisfies
the rule that states a method that may cause an exception
to be thrown must be defined showing explicitly which
exception it can throw.

// while checked exceptions must be caught,
// runtime exceptions may be caught

Notice we didn't have to add a throws clause to main( )
in the earlier example, when we were dealing with
the
ArithmeticException. This is because ArithmeticException
is a runtime exception.

As was discussed earlier, the Java programmer is not
mandated to catch runtime exceptions. Not
to say it
would not have been a good idea! Nothing stops us from
catching
runtime exceptions.

The following code is included to demonstrate that runtime
exceptions may be caught like other exceptions. We are
ahead of ourselves again, as the try catch block is discussed
later in this note.


Example of a Runtime Exception Being Caught
Using a try catch Block


class TroubleFix{

  public static void main(String[] args) {
    try{
      int x =1 / 0;
      System.out.println(x + " But x will never be printed!");
      }
   catch(RuntimeException re){
      System.out.println("\n " + "Error Description: " + "\"" + re.getMessage( ) + "\"");
      } 
      System.out.println("Proceeding Like Nothing Happened!" + "\n ");
      }
   }  


Error Handling Strategies



There are three strategies one can describe when dealing
with exceptions. The first is more a lack of strategy, 'Don't
do anything at all!'. It is possible to take this approach
and you get the expected results. The second is to defer
dealing with the exception to a higher scope. The second
approach may be described as passing the problem on.
The final strategy is to use 'try catch and finally' blocks
to handle the occurrence of exceptions.


1. Do Nothing

The first case scenario, to do nothing, is not really a stategy.
It is more a matter of stating the simplest scenario where an
Exception will inevitably be thrown. The Java compiler only
allows you to get away with this with RunTime and Error
exceptions. The following example shows an exception
waiting to happen.


Example
 
class Trouble{

  public static void main(String[] args) {
    int x =1 / 0;
    System.out.println("We will never see this line printed");
    }
     

// this will compile but an exception will be thrown at runtime

Observe the class provides no plan to deal with the exception
it is set to create. In this case the exception is thrown in the
main( ) method. Since main is the program's point of entry, it
doesn't have far to go before being registered as an exception
with the user. The Exception object is created and passed to
the runtime which prints an error report to console stating an
ArithmeticException has been thrown and exits the program.
If you look at the class exception hierarchy shown earlier you
will find ArithmeticException is a RuntimeException sub-class.

Dividing by zero with floating point numbers


/* Floating point numbers will not throw the  runtime ArithmeticException. Instead  as mandated by the IEEE floating point standard a floating point number reports INFINITY when a divide by zero using floating point  numbers is performed.  */

class X1{
          public static void main(String[] args) {
             System.out.println("Div Test");
             double s=60;
             double t=0;
             double d = s / t;
             System.out.println(d);  // prints 'Infinity'
             }
       }


2. Pass the Exception On with a 'throws' Statement

The keyword 'throw' causes an exception to be thrown.
On the other hand, the keyword 'throws' is used differently.
This keyword is appended to a method's signature to show
the method is capable of throwing an exception. The throws
clause declares that the use of the given method may result
in an exception (of the type declared) being thrown.

This exception, if it is not handled by appropriate code
locally, will be passed 'up' into the next highest scope
containing this method call. The following example shows
how a throws clause is appended to a method signature.


Declaration of the sleep( ) method Showing 'throws'

public static void sleep(long millis) throws InterruptedException

// The sleep( ) method is a static Thread class method.
// It has a couple overloaded forms. The commonest form
// takes an int value representing milliseconds.


Any method that throws an exception (and does handle
the exception itself ) must
be itself declare it throws that
exception. In the following example, the rest method
is
defined calling sleep within it. ( Notice it calls the static
method sleep, off of the
Thread class name. This is good
form as it signals the reader that sleep is a static
method.)

Example of a Method Needing to Declare it Throws an Exception

public void rest( ) throws InterruptedException{
    Thread.sleep(60000);
      // sleep might be interrupted and throw InteruptedException
     }

Because sleep can throw an InterruptedException, the
compiler now requires the
enclosing method, rest( ), to
declare it throws this exception. If rest( )
is now called
in another method that method too must be declared as
throwing InterruptedException and so on all the way up
to main( ). There is an alternative. The new methods can
be written to handle any exceptions that occur.

This approach is useful in defining one or a set of methods
that may cause an exception to be thrown. In the final
analysis you will need to use Java's technique for
handling exceptions using 'try', 'catch' & 'finally' blocks.
 

3. Handle the Exception with try catch & finally blocks

The mechanism Java provides for disposing of or handling
exceptions that might arise in a program are flow control
structures called 'try catch and finally' blocks. Any method
that may throw an exception  is 'called' from inside the try
block. A catch block is provided to handle the exception
should that exception be thrown. The optional 'finally' block
is called in any event barring the underlying operating system
failing or
cutting power to the machine. The 'try catch finally'
blocks take the following form.

Form of the 'try', 'catch' 'finally' Block

try { // block } opt.[ catch ( Exception e ) ] opt.[ finally { // block } ] 


The following example shows how the rest( ) method
might be rewritten in order to handle the exception
thrown by sleep( ).

Method That Throws an Exception Rewritten
to Catch the Exception


 public void rest( ){
      try{
          Thread.sleep(60000);
          }
      catch(InterruptedException ie){
          System.out.println("Interrupted Exception");
         }


Rules Governing the Use of 'try catch & finally'  Blocks

There are a number of rules that describe the use of these
exception handling structures. First, for any try block there
has to be at least one catch or finally statement. (Even an
empty try block insists on having either a catch or finally
statement.)


Example Showing  a 'try' with a 'finally' Block

try{
   System.out.println("No exception possibility");
   }
finally{
        System.out.println("Still need a catch or a finally statemenet");
        }
 

The 'catch' to the above combination is that it only compiles
if the try block is incapable of throwing an exception which
sort of defeats the purpose of using the try block in the first
case. In the usual case, the try block will contain a method
that may lead to an exception being thrown. In this case a
'catch' block must be provided. The compiler will always tell
you if this is the case.

// could still be useful to make sure something is always
// done in the event that an unknown exception is thrown


Example Showing a Typical 'try' 'catch' Combination.

  try{
       Thread.sleep( 1000 );
         }
  catch(InterruptedException ie){
        System.out.println("Need a catch statment if an exception may be thrown");
        }


The second rule is that there can at most only one finally
statement. There can however be any number of catch
statements.

A third rule may be described. Exception subclasses
must be caught before their more general parent classes.
Both notions described in rule last two rules are captured
in the following example.

Specialized Exceptions are handled before more General
Exceptions
// also examples a complete try catch finally Construct

class ExRules{
public static void main(String[]args){

System.out.println("Starting a three second wait...");
try{
   Thread.sleep( 3000 );
   }   
catch(InterruptedException ie){
   System.out.println
    ("Need a catch statement if an exception may be thrown");
   }
catch(Exception ie){
    System.out.println
    ("The more general exception must follow the subclass");
    }
// the compiler would not let this catch clause be
// placed before
the one above it
finally{
   System.out.println
   ("The compiler will only allow a single finally block");
          }
  }
}

Following is a brief summary of the rules governing
the use of try catch finally blocks.


Summary of Exception Rules


Handling Multiple Exceptions



In the following code section of an imaginary method, a
variety of things can happen
which effects the control
path taken.

Code sample

             //  ...
             // somewhere inside a method
             //...
       try{
             // exceptions waiting to happen
            }
       catch( SubException es){
         // say or do something
             }
       catch( AnotherException ea){
         // say or do something
             }
       catch( ParentException ep){
         // say or do something
             }
       finally{
         // code executed in any case
             }
        // the line following the finally block 
       //  ...


No Exception Occurs

If no exception occurs, the code in the try block finishes
execution, the finally
block executes and execution
resumes at the line following the finally block.


A SubException Occurs

If a SubException is thrown, execution leaves the try
block at the point the exception
was raised and goes
to the catch block associated with SubException. After
this code
is executed, the finally block is executed and
execution proceeds at the line following
the finally block.


ParentException is Thrown

If a ParentException is thrown, execution exits the try
block and proceeds at the catch
block associated with
the ParentException. Once this block executes, the
finally block
executes and control proceeds at the line
following the finally block.


An Unknown Exception Occurs

If an unknown exception occurs, execution proceeds
directly to the finally block. When
the finally block is
finished executing, control leaves the method entirely.
This is an
uncaught exception which will next appear
in the next enclosing scope.



Stack Tracing



The Exception Class

The Exception class has a couple constructor forms and
several useful methods which
can be used to augment
the information that is returned when an exception occurs.

For an example look at the end of the assignment section.
 

 Exception Constructors

public
Exception( )

Constructs an Exception with
no specified detail message.

public
Exception(String s)

Constructs an Exception with
the specified detail message.

 Methods inherited from Throwable       // 3 of 7 methods

String 
getMessage( ) 

Returns the error message string
of this throwable object.

void 
printStackTrace
( )

Prints this Throwable and its backtrace
to the standard error stream.

// there are two more printStackTrace
// methods, one prints the stack
trace
// to a specified print steam and another
// prints to a PrintWriter

String 
toString( ) 

Returns a short description of this throwable object.


Using printStackTrace( )

The printStackTrace( ) method is useful to unravel a set
of events that lead back to the location where the error
occurred. Following is some Java code that makes
several nested calls that inevitably lead to an exception
being thrown. The printStackTrace( ) method is called
to trace through the call stack back to where the error
occurred.
 

The Call Stack

Method calls are, at the machine level, directives to go
to an address and run the list of
instructions that are
stored there. If from this location a call is made to a
nested method,
information about the first method has
to be stored somewhere while the computer is
busy
attending to the new block of information.

The Stack
" A stack is an abstract data type and data structure based
on the principle of Last In First Out (LIFO). . . .Among other
uses, stacks are used to run a Java Virtual Machine, and the
Java
language itself has a class called "Stack", which can
be used by the programmer. "                         - wikipedia

PS.
 It's like the PEZ candy dispenser ->
 PUSH in the candy  --> POP it out
 Last in is first out!


The computer uses a data structure
called a 'stack'
to store the details of where in a method's instruction
list execution is at. Be
fore going off to execute a
new block of code state information is stored so that
everything can pick up at the same place when the
branch code returns. (The following is a figurative

description of what goes on inside the runtime
environment at the machine level. )


Diagram of nested methods being called in a series

main( ) |
        | --getA( ) |
                      |
                      | --getB( ) |
                                     |
                                     |---getC( ) |
                                                    |
                                                    |   // exception thrown
 


The stack trace shows the path in reverse order of how
it was traversed to get to
the point where the exception
was thrown . 

The following code sets up a nested set of methods that
will end up throwing an
exception. The printStackTrace
method is used to show the behavior that occurs
when an
exception is thrown.

 

Example

public class Trace{
public static void main(String[]args){
    getA( );        
    // line calling the method that calls the
    // method that calls the 'bad' method

    }
    static void getA( ){
       getB( );     
   // line calling method that calls the bad method

    }
   static void getB( ){
       getC( );         // line with first call on bad method
    }
    static void getC( ){
     try{
        int i=1;
        int j=0;
        int k= i /j;    // line where the trouble starts
       }
       catch (ArithmeticException ae){
          ae.printStackTrace( );  
// here is the printStackTrace( ) method being called

      }
   }
}

This code results in the following output to the command
line. Notice the stack trace reports from where the error
occurred proceeding to report as it works back up the
calling stack finally to main.
 

Output of the printStackTrace( ) method

C:\NewCode>java Trace
 
java.lang.ArithmeticException: / by zero
        at Trace.getC(Trace.java:15)
        at Trace.getB(Trace.java:9)
        at Trace.getA(Trace.java:6)
        at Trace.main(Trace.java:3)

 


Using the getMessage( ) method

The getMessage( ) method is used to return the String
message that is passed into the Exception
constructor
that is designed to receive an error message.


Example
 

public Exception(String s)   // getMessage( ) returns String


For example a class can be built extending the Exception
class, building a constructor that
accepts a String object
and then invoking the appropriate parent constructor using
a super
( ) constructor call.


Example

class PowerDown extends Exception{
        PowerDown ( String reason ){
             super(reason);
             }
   // no args constructor
         PowerDown( ){  }     
                }


The new Exception class can then be used in different
circumstances and the
getMessage( ) method can return
a variety of appropriately related messages.


Example 2  

class Reactor {
    static int temp;
  public static void main(String[]args){
     temp =(int)( Math.random( )*2400 ) ;
         try {
            if(temp>2000)
               throw new PowerDown("temperature too high");
               else if( temp< 200)
               throw new PowerDown("temperature too low");
               }
         catch(PowerDown pd){
         System.out.println(pd.getMessage( ));
         }
      }
   }


Supplemental


Assertions 
   //   for reference, not on final 

There are implicit assumptions in most programs we write.
Though humans think
they are obvious, computers don't.
An example, we think of our ages as being only
positive
numbers while computers have no problem with a person
being -3.

Another example, we assume that interest rate at the
bank is a positive value while charges are subtracted

from our accounts. We would not be comfortable with
a negative interest rate although
we might not mind
negative charges being subtracted from our account.

What seems illogical to us is often feasible for the
computer. A technique to test for different
assumptions
we make is referred to as making 'assertions'.

An assertion is an assumption you believe to be true.
Assertions are used to help
assure quality control of
software, so that it is as bug free as possible. The
following
examples are from Cay Hoorstman's
'Computing Concepts with Java 2 Essentials'. It has
been supplemented with some real values and a main
method where it's methods are called.

Example Adapted from Cay Hoorstman's 'Computing
Concepts with Java 2 Essentials'

// supplemented with values and main( )

public class Assertion{
static double root=0;

    public static void check(boolean b){
     if (!b){
        System.out.println("Assertion failed");
        new Throwable( ).printStackTrace( );
        System.exit(1);
        }
     }  

public void computeIntersection( ){
           
          double r=.5;
          double x=.1;
          double a=.001;
         double y = r * r -( x - a ) * ( x - a );

 // if we insert y = - 1  the assertion check
method will
// throw us out of the program before the sqrt( ) method
// is called
double y= -1;

      Assertion.check(y>=0);

// the assertion check provides assurance y is not negative
// before calling the square root on the number . Calling this
// function on an negative number yields NaN


        root = Math.sqrt(y);
         }

public static void main(String[]args){
Assertion a=new Assertion();
a.computeIntersection( );
System.out.println("Root: " + root);
}
}

If an Exception is thrown by the assertion it will show
up in the stack trace.

 

The 'asserts' Keyword    // only for reference

To simplify and perhaps ensure uniform implementation
Java has added the 'asserts'
keyword to the JDK1.4 to
do assertions. This will have immediate impact on old

code created before JDK 1.4.x.  If this code was unlucky
enough to have used the
'asserts' word as an identifier
an compiler error will result. The compiler is supplying a
transitional accommodation
where it will temporally allow
asserts to co-exist as an identifier or as a keyword.

Practically we can consider 'asserts' to be a keyword
from this point forward.

The 'asserts' keyword takes care of creating testing code
and may be left in code
after assertion testing as a protection
against further modifications that may result
in bugs.

Java allows the assertion to be put into effect by using
an 'enableassertions' flag at the command line with the
java command. The short form one is '-ea'.

The following code shows the simple form asserts
takes. Here if an expression following the asserts
keyword evaluates to false, an assertionError is
thrown. Note this only happens if the assertion flag
is on.


Code with a Simple Assertion
  // age is greater than 19

class AssertNightClubRule{
public static void main(String[] args){
     int age= 16;
     assert (age>19);
     System.out.println("No assertion of age");
     }
}

OUTPUT // with flag off

> java   AssertNightClubRule
No assertion of age

OUTPUT // with flag on

>java -ea  AssertNightClubRule
Exception in thread "main" java.lang.AssertionError
        at Assert.main(Assert.java:4)

 


Self Test                            Self Test With Answers



1) Select the incorrect statement.

a) Checked exceptions arise in a correct program.
b) In a correct program, runtime exceptions  should never occur.
c) You are not expected to handle Error class objects.
d) Throwable are a subclass of the Checked Exception category


2) The following code will

  class Dv{
               public static void main(String[] args) {
                 System.out.println("Running Test");
                 int x =1 / 0;
                }
         }

a) not compile
b) compile but fail to run
c) compile and run and throw a runtime exception
d) compile and run successfully without error reports


3)  The sleep method throws InterruptedException.
     What will the following code do?

 class X2{
     public static void main(String args[]) throws InterruptedException {
         Thread.sleep(100);
         }
     }

a) does not compile
b) compiles but fails to run
c) compiles and runs and throws a runtime exception
d) compiles and runs successfully but may throw an exception
 

4) Which of the following statements regarding  exceptions is not correct?

a) there can only be one finally block
b) for every try block there must be either a catch or finally block
c) for every try and catch block there must also be a finally block
d) there can be any number of catch blocks
 


Exercise  Good Luck on the Exam!



Use the examples in the note to answer the following questions.

Q1.Write a class with no error protection that throws a divide by zero exception.
      // shows doing nothing

Q2.Write an exception class called Flat and throw it from an if clause
     with a boolean value,
NoAir. (Don't use try and catch in this question.
     This will require declaring main( ) as
throwing the exception.)
 
// shows throws being used

Q3 In a try clause throw Exception. In the corresponding catch clause
     catch the Exception
object.On catching it, print to screen "Exception
    caught", and from a finally block, print
to screen the word continuing.   
// demonstates try catch finally

Q5  Create an extension of Exception that uses the constructor of the
      Exception class that allows a string message to be provided. You
      will need to use super( ) to invoke the parent constructor to get this
      behaviour in your extension of the Exception class.
Then use the
      getMessage( ) method to extract this
string when the exception is
      thrown.

      ( If you have trouble with this question, don't fight it too long. A
       sample of code that illustrates this formulation is included at the
      end of the note. )
 
      // shows getMessage( ) in use 


Q5. Create a system of methods that nest an error. Use the
      printStackTrace method 
to trace the error through the call stack.     
         // shows printStackTrace( ) in use

 


Example

class MotorFailure extends Exception{
   MotorFailure(String cause){
   super(cause);
   }
}        // should really add the no-args constructor as well
         // now in case someone extends this class

// Now this exception class can be instantiated with the constructor
// that takes a descriptive
string. This string is returned if getMessage( )
// is called on the exception object thrown.

class MotorTest{
public static void main(String[]args){
 try {
       throw new MotorFailure("blown gasket");
      }
      catch(MotorFailure mf){
           System.out.println( mf.getMessage( ));
          }
    }
}