19.4. Problem Solving Using Recursion

 
[Page 582 ( continued )]

17.4. Understanding Exception Handling

Java's exception-handling model is based on three operations: declaring an exception , throwing an exception , and catching an exception , as shown in Figure 17.4.

Figure 17.4. Exception handling in Java consists of declaring exceptions, throwing exceptions, and catching and processing exceptions.


[Page 583]

17.4.1. Declaring Exceptions

In Java, the statement currently being executed belongs to a method. The Java interpreter invokes the main method for a Java application, and the Web browser invokes the applet's no-arg constructor and then the init method for a Java applet. Every method must state the types of checked exceptions it might throw. This is known as declaring exceptions . Because system errors and runtime errors can happen to any code, Java does not require that you declare Error and RuntimeException (unchecked exceptions) explicitly in the method. However, all other exceptions thrown by the method must be explicitly declared in the method declaration so that the caller of the method is informed of the exception.

To declare an exception in a method, use the throws keyword in the method declaration, as in this example:

   public void   myMethod()   throws   IOException 

The throws keyword indicates that myMethod might throw an IOException . If the method might throw multiple exceptions, add a list of the exceptions, separated by commas, after throws :

   public void   myMethod()   throws   Exception1, Exception2, ..., ExceptionN 

Note

If a method does not declare exceptions in the superclass, you cannot override it to declare exceptions in the subclass.


17.4.2. Throwing Exceptions

A program that detects an error can create an instance of an appropriate exception type and throw it. This is known as throwing an exception . Here is an example: Suppose the program detected that an argument passed to the method violates the method contract (e.g., the argument must be non-negative, but a negative argument is passed); the program can create an instance of IllegalArgumentException and throw it, as follows :

 IllegalArgumentException ex =   new   IllegalArgumentException(   "Wrong Argument"   );   throw   ex; 

Or if you prefer, you can use the following:

   throw new   IllegalArgumentException(   "Wrong Argument"   ); 

Note

IllegalArgumentException is an exception class in the Java API. In general, each exception class in the Java API has at least two constructors: a no-arg constructor, and a constructor with a String argument that describes the exception. This argument is called the exception message , which can be obtained using getMessage() .


Tip

The keyword to declare an exception is throws , and the keyword to throw an exception is throw .


17.4.3. Catching Exceptions

You now know how to declare an exception and how to throw an exception. When an exception is thrown, it can be caught and handled in a try-catch block, as follows:

   try   { statements;  // Statements that may throw exceptions  } 

[Page 584]
   catch   (Exception1 exVar1) { handler for exception1; }   catch   (Exception2 exVar2) { handler for exception2; } ...   catch   (ExceptionN exVar3) { handler for exceptionN; } 

If no exceptions arise during the execution of the try block, the catch blocks are skipped .

If one of the statements inside the try block throws an exception, Java skips the remaining statements in the try block and starts the process of finding the code to handle the exception. The code that handles the exception is called the exception handler ; it is found by propagating the exception backward through a chain of method calls, starting from the current method. Each catch block is examined in turn , from first to last, to see whether the type of the exception object is an instance of the exception class in the catch block. If so, the exception object is assigned to the variable declared and the code in the catch block is executed. If no handler is found, Java exits this method, passes the exception to the method that invoked the method, and continues the same process to find a handler. If no handler is found in the chain of methods being invoked, the program terminates and prints an error message on the console. The process of finding a handler is called catching an exception .

Suppose the main method invokes method1 , method1 invokes method2 , method2 invokes method3 , and an exception occurs in method3 , as shown in Figure 17.5. Consider the following scenario:

  • If method3 cannot handle the exception, method3 is aborted and the control is returned to method2 . If the exception type is Exception3 , it is caught by the catch block for handling exception ex3 in method2 . statement5 is skipped, and statement6 is executed.

  • If the exception type is Exception2 , method2 is aborted, the control is returned to method1 , and the exception is caught by the catch block for handling exception ex2 in method1 . statement3 is skipped, and statement4 is executed.


    [Page 585]
  • If the exception type is Exception1 , method1 is aborted, the control is returned to the main method, and the exception is caught by the catch block for handling exception ex1 in the main method. statement1 is skipped, and statement2 is executed.

  • If the exception type is not Exception1 , Exception2 , or Exception3 , the exception is not caught and the program terminates. statement1 and statement2 are not executed.

Figure 17.5. If an exception is not caught in the current method, it is passed to its caller. The process is repeated until the exception is caught or passed to the main method.
(This item is displayed on page 584 in the print version)

Note

Various exception classes can be derived from a common superclass. If a catch block catches exception objects of a superclass, it can catch all the exception objects of the subclasses of that superclass.


Note

The order in which exceptions are specified in catch blocks is important. A compilation error will result if a catch block for a superclass type appears before a catch block for a subclass type. For example, the ordering in (a) is erroneous, because RuntimeException is a subclass of Exception . The correct ordering should be as shown in (b).


Note

Java forces you to deal with checked exceptions. If a method declares a checked exception (i.e., an exception other than Error or RuntimeException ), you must invoke it in a try-catch block or declare to throw the exception in the calling method. For example, suppose that method p1 invokes method p2 , and p2 may throw a checked exception (e.g., IOException ), you have to write the code as shown in (a) or (b).


17.4.4. Getting Information from Exceptions

An exception object contains valuable information about the exception. You may use the following instance methods in the java.lang.Throwable class to get information regarding the exception, as shown in Figure 17.6. The printStackTrace() method prints stack trace information on the console. The getStackTrace() method provides programmatic access to the stack trace information printed by printStackTrace() .


[Page 586]
Figure 17.6. Throwable is the root class for all exception objects.

Listing 17.3 gives an example that uses the methods in Throwable to display exception information. Line 4 invokes the sum method to return the sum of all the elements in the array. There is an error in line 23 that causes the ArrayIndexOutOfBoundsException , a subclass of IndexOutOfBoundsException . This exception is caught in the try-catch block. Lines 7, 8, 9 display the stack trace, exception message, and exception object and message using the printStackTrace() , getMessage() , and toString() methods, as shown in Figure 17.7. Line 12 obtains stack trace elements into an array. Each element represents a method call. You can obtain the method (line 14), class name (line 15), and exception line number (line 16) for each element.

Figure 17.7. You can use the printStackTrace() , getMessage() , toString() , and getStackTrace() methods to obtain information from exception objects.

Listing 17.3. TestException.java
(This item is displayed on pages 586 - 587 in the print version)
 1   public class   TestException { 2   public static void   main(String[] args) { 3   try   { 4 System.out.println(  sum(   new int   [] {   1   ,   2   ,   3   ,   4   ,   5   })  ); 5 } 6   catch   (Exception ex) { 7 ex.printStackTrace(); 8 System.out.println(   "\n"   + ex.getMessage()); 9 System.out.println(   "\n"   + ex.toString()); 10 11 System.out.println(   "\nTrace Info Obtained from getStackTrace"   ); 12 StackTraceElement[] traceElements = ex.getStackTrace(); 

[Page 587]
 13   for   (   int   i =     ; i < traceElements.length; i++) { 14 System.out.print(   "method "   + traceElements[i].getMethodName()); 15 System.out.print(   "("   + traceElements[i].getClassName() +   ":"   ); 16 System.out.println(traceElements[i].getLineNumber() +   ")"   ); 17 } 18 } 19 } 20 21   private static int   sum(   int   [] list) { 22   int   result =     ; 23   for   (   int   i =     ;  i <= list.length  ; i++) 24 result += list[i]; 25   return   result; 26 } 27 } 

17.4.5. Example: Declaring, Throwing, and Catching Exceptions

This example demonstrates declaring, throwing, and catching exceptions by modifying the setRadius method in the Circle2 class in Listing 7.3. The new setRadius method throws an exception if the radius is negative.

Rename the circle class given in Listing 17.4 as CircleWithException , which is the same as Circle2 except that the setRadius(double newRadius) method throws an IllegalArgumentException if the argument newRadius is negative.

Listing 17.4. CircleWithException.java
(This item is displayed on pages 587 - 588 in the print version)
 1   public class   CircleWithException { 2  /** The radius of the circle */  3   private double   radius; 4 5  /** The number of the objects created */  6   private static int   numberOfObjects =     ; 7 8  /** Construct a circle with radius 1 */  9   public   CircleWithException() { 10   this   (   1.0   ); 11 } 12 13  /** Construct a circle with a specified radius */  14   public   CircleWithException(   double   newRadius) { 15  setRadius(newRadius);  16 numberOfObjects++; 17 } 18 19  /** Return radius */  20   public double   getRadius() { 21   return   radius; 22 } 23 24  /** Set a new radius */  25   public void   setRadius(   double   newRadius) 26    throws   IllegalArgumentException  { 27   if  (newRadius >=    ) 28 radius = newRadius; 29   else   30    throw new   IllegalArgumentException(  

[Page 588]
 31    "Radius cannot be negative"   );  32 } 33 34  /** Return numberOfObjects */  35   public static int   getNumberOfObjects() { 36   return   numberOfObjects; 37 } 38 39  /** Return the area of this circle */  40   public double   findArea() { 41   return   radius * radius *   3.14159   ; 42 } 43 } 

A test program that uses the new Circle class is given in Listing 17.5. Figure 17.8 shows a sample run of the test program.

Figure 17.8. The exception is thrown when the radius is negative.

Listing 17.5. TestCircleWithException.java
 1   public class   TestCircleWithException { 2  /** Main method */  3   public static void   main(String[] args) { 4    try   {  5 CircleWithException c1 =   new   CircleWithException(   5   ); 6 CircleWithException c2 =   new   CircleWithException(   -5   ); 7 CircleWithException c3 =   new   CircleWithException(     ); 8  }  9    catch   (IllegalArgumentException ex) {  10 System.out.println(ex); 11  }  12 13 System.out.println(   "Number of objects created: "   + 14 CircleWithException.getNumberOfObjects()); 15 } 16 } 

The original Circle2 class remains intact except that the class name is changed to CircleWithException , a new constructor CircleWithException(newRadius) is added, and the setRadius method now declares an exception and throws it if the radius is negative.

The setRadius method declares to throw IllegalArgumentException in the method declaration (lines 25 “26 in CircleWithException.java). The CircleWithException class would still compile if the throws IllegalArgumentException clause were removed from the method declaration, since it is a subclass of RuntimeException and every method can throw RuntimeException (unchecked exception) regardless of whether it is declared in the method header.

The test program creates three CircleWithException objects, c1 , c2 , and c3 , to test how to handle exceptions. Invoking new CircleWithException(-5) (line 6 in Listing 17.5) causes the setRadius method to be invoked, which throws an IllegalArgumentException , because the radius is negative. In the catch block, the type of the object ex is IllegalArgumentException , which matches the exception object thrown by the setRadius method. So this exception is caught by the catch block.


[Page 589]

The exception handler prints a short message, ex.toString() (line 10), about the exception, using System.out.println(ex) .

Note that the execution continues in the event of the exception. If the handlers had not caught the exception, the program would have abruptly terminated .

The test program would still compile if the try statement were not used, because the method throws an instance of IllegalArgumentException , a subclass of RuntimeException (unchecked exception). If a method throws an exception other than RuntimeException and Error , the method must be invoked within a try-catch block.

Note

As you will learn in Chapter 24, "Multithreading" Java supports multithreading. One program can have many threads. Methods are executed on threads. If an exception occurs on a thread, the thread is terminated if the exception is not caught. If a program has only one thread, an uncaught exception will cause the program to terminate. If a program has multiple threads , an uncaught exception will terminate only the thread where the exception occurred. However, since certain threads may rely on the terminated thread, terminating a thread may affect the rest of the program.


 


Introduction to Java Programming-Comprehensive Version
Introduction to Java Programming-Comprehensive Version (6th Edition)
ISBN: B000ONFLUM
EAN: N/A
Year: 2004
Pages: 503

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net