Previous Table of Contents Next


14.2.13.7. Defining and Generating Exceptions

You can signal your own exceptions with the throw statement. The throw keyword must be followed by an object that is Throwable or a subclass. Often, exception objects are allocated in the same statement that they are thrown in:

   throw new MyException(“my exceptional condition occurred.”);

When an exception is thrown, normal program execution stops and the interpreter looks for a catch clause that can handle the exception. Execution propagates up through enclosing statements and through invoking functions until such a handler is found. Any finally blocks that are passed during this propagation are executed.

Using exceptions is a good way to signal and handle errors in your own code. By grouping all your error handling and recover code together within the try/catch/finally structure, you will end up with cleaner code that is easier to understand. Sometimes, when you are throwing an exception, you can use one of the exception classes already defined by Java API. Often, though, you will want to define and throw your own exception types.

Example 14.6 shows how you can define your own exception types, throw them, and handle them. It also helps clarify how exceptions propagate. It is a long example, but worth studying in some detail. You’ll know you understand exception handling if you can answer the following: What happens when this program is invoked with no argument; with a string argument; and with integer arguments 0, 1, 2, and 99?

EXAMPLE 14.6. Defining, throwing, and handling exceptions.

   // Here we define some exception types of our own.
   // Exception classes generally have constructors but no data or
   // other methods. All these do is call their superclass constructors.
   class MyException extends Exception {
     public MyException() { super(); }
     public MyException(String s) { super(s); }
   }
   class MyOtherException extends Exception {
     public MyOtherException() { super(); }
     public MyOtherException(String s) { super(s); }
   }
   class MySubException extends MyException {
     public MySubException() { super(); }
     public MySubException(String s) { super(s); }
   }

   public class throwtest {
     // This is the main() method. Note that it uses two
     // catch clauses to handle two standard Java exceptions.
   public static void main(String argv[]) {
       int i;

       // First, convert our argument to an integer.
       // Make sure we have an argument and that it is convertible.
       try {  i = Integer.parseInt(argv[0]);  }
       catch (ArrayIndexOutOfBoundsException e) { // argv is empty
         System.out.println(“Must specify an argument”);
         return;
       }
       catch (NumberFormatException e) { // argv[0] isn’t an integer
         System.out.println(“Must specify an integer argument.”);
         return;
       }

       // Now, pass that integer to method a().
       a(i);
     }

     // This method invokes b(), which is declared to throw
     // one type of exception. We handle that one exception.
     public static void a(int i) {
       try {
         b(i);
       }
       catch (MyException e) {           // Point 1
         // Here we handle MyException and its subclass MySubException.
         if (e instanceof MySubException)
           System.out.print(“MySubException: “);
         else
           System.out.print(“MyException: “);
         System.out.println(e.getMessage());
         System.out.println(“Handled at point 1”);
       }
     }

     // This method invokes c(), and handles one of the two exception
     // types that that method can throw. The other exception type is
     // not handled, and is propagated up and declared in this method’s
     // throws clause. This method also has a finally clause to finish
     // up the work of its try clause. Note that the finally clause is
     // executed after a local catch clause, but before a containing
     // catch clause or one in an invoking procedure.
     public static void b(int i) throws MyException {
       int result;
       try {
         System.out.print(“i = “ + i);
         result = c(i);
         System.out.print(“ c(i) = “ + result);
       }
       catch (MyOtherException e) {             // Point 2
         // Handle MyOtherException exceptions:
         System.out.println(“MyOtherException: “ + e.getMessage());
         System.out.println(“Handled at point 2”);
       }
       finally {
         // Terminate the output we printed above with a newline.
         System.out.print(“\n”);
       }
     }

     // This method computes a value or throws an exception.
     // The throws clause only lists two exceptions, because
     // one of the exceptions thrown is a subclass of another.
     public static int c(int i) throws MyException, MyOtherException {
       switch (i) {
       case 0:      // processing resumes at point 1 above
         throw new MyException(“input too low”);
       case 1:      // processing resumes at point 1 above
         throw new MySubException(“input still too low”);
       case 99:     // processing resumes at point 2 above
         throw new MyOtherException(“input too high”);
       default:
         return i*i;
       }
     }
   }

14.2.14. Miscellaneous Differences

A number of miscellaneous differences between Java and C are described in the sections that follow. Miscellaneous differences that were mentioned elsewhere, such as the lack of the goto statement and the sizeof operator, are not repeated here.

14.2.14.1. Local Variable Declarations

A feature that Java has borrowed from C++ is the ability to declare and initialize local variables anywhere in a method body or other block of code. Declarations and their initializers no longer have to be the first statements in any block—you can declare them where it is convenient and fits well with the structure of your code.

Don’t let this freedom make you sloppy, however! For someone reading your program, it is nice to have variable declarations grouped together in one place. As a rule of thumb, put your declarations at the top of the block, unless you have some good organizational reason for putting them elsewhere.


Previous Table of Contents Next