|
The Essence of OOP using Java, Exception Handling By Richard G. Baldwin September 3, 2002 You have a choice Therefore, when writing exception handlers, you have a choice. You can write a handler whose exception type corresponds to a node in the inheritance hierarchy, and it will be appropriate to catch exceptions of that type, or any subclass of that type. Alternately, you can write a handler whose exception type corresponds to a leaf, in which case, it will be appropriate to catch exceptions of that type only. And finally, you can mix and match, writing some exception handlers whose type corresponds to a node, and other exception handlers whose type corresponds to a leaf. In all cases, however, be sure to position your exception handlers in reverse subclass order, with the furthermost subclass from the root appearing first, and the root class appearing last. The finally block And finally (no pun intended), Campione and Walrath tell us:
To elaborate, the finally block can be used to provide a mechanism for cleaning up open files, etc., before allowing control to be passed to a different part of the program. You accomplish this by writing the cleanup code within a finally block. Code in finally block is always executed It is important to remember that the runtime system always executes the code within the finally block regardless of what happens within the try block. If no exceptions are thrown, none of the code in catch blocks is executed, but the code in the finally block is executed. If an exception is thrown and the code in an exception handler is executed, once the execution of that code is complete, control is passed to the finally block and the code in the finally block is executed.
The power of the finally block The sample program shown in Listing 5 illustrates the power of the finally
block.
Execute return statement in catch block The code in Listing 5 forces an ArithmeticException by attempting to do an integer divide by zero. Control is immediately transferred to the matching catch block, which prints a message and then executes a return statement. Normally, execution of a return statement terminates the method immediately. In this case, however, before the method terminates and returns control to the calling method, the code in the finally block is executed. Then control is transferred to the main method, which called this method in the first place. Figure 8 shows the output produced by this program.
This program demonstrates that the finally block really does have the final word. Declaring exceptions thrown by a method Sometimes it is better to handle exceptions in the method in which they are detected, and sometimes it is better to pass them up the call stack and let another method handle them. In order to pass exceptions up the call stack, you must declare them in your method signature. To declare that a method throws one or more exceptions, you add a throws clause to the method signature for the method. The throws clause is composed of the throws keyword followed by a comma-separated list of all the exceptions thrown by that method. The throws clause goes after the method name and argument list and before the curly bracket that defines the scope of the method. Figure 9 shows the syntax for declaring that a method throws four
different types of exceptions.
Assuming that these are checked exceptions, any method calling this method would be required to either handle these exception types, or continue passing them up the call stack. Eventually, some method must handle them or the program won't compile.
The throw keyword Before your code can catch an exception, some Java code must throw one. The exception can be thrown by code that you write, or by code that you are using that was written by someone else. Regardless of who wrote the code that throws the exception, it's always thrown with the Java throw keyword. At least that is true for exceptions that are thrown by code written in the Java language.
A single argument is required When formed into a statement, the throw keyword requires a single
argument, which must be a reference to an object instantiated from the
Throwable class, or any subclass of the Throwable class. Figure
10 shows an example of such a statement.
If you attempt to throw an object that is not instantiated from Throwable or one of its subclasses, the compiler will refuse to compile your program. Defining your own exception classes Now you know how to write exception handlers for those exception objects that are thrown by the runtime system, and thrown by methods in the standard class library. It is also possible for you to define your own exception classes, and to cause objects of those classes to be thrown whenever an exception occurs. In this case, you get to decide just what constitutes an exceptional condition. For example, you could write a data-processing application that processes integer data obtained via a TCP/IP link from another computer. If the specification for the program indicates that the integer value 10 should never be received, you could use an occurrence of the integer value 10 to cause an exception object of your own design to be thrown. Choosing the exception type to throw Before throwing an exception, you must decide on its type. Basically, you have two choices in this regard:
An important question So, an important question is, when should you define your own exception classes and when should you use classes that are already available. Because this is only one of many design issues, I'm not going to try to give you a ready answer to the question. However, I will refer you to The Java Tutorial by Campione and Walrath where you will find a checklist to help you make this decision. Choosing a superclass to extend If you decide to define your own exception class, it must be a subclass of Throwable. You must decide which class you will extend. The two existing subclasses of Throwable are Exception and Error. Given the earlier description of Error and its subclasses, it is not likely that your exceptions would fit the Error category. (In concept, errors are reserved for serious hard errors that occur deep within the system.) Checked or unchecked exception Therefore, your new class should probably be a subclass of Exception. If you make it a subclass of RuntimeException, it won't be a checked exception. If you make it a subclass of Exception, but not a subclass of RuntimeException, it will be a checked exception. Only you can decide how far down the Exception hierarchy you want to go before creating a new branch of exception classes that are unique to your application. Naming conventions Many Java programmers append the word Exception to the end of all class names that are subclasses of Exception, and append the word Error to the end of all class names that are subclasses of Error. One more sample program Let's wrap up this lesson with one more sample program named Excep16. We will define our own exception class in this program. Then we will throw, catch and process an exception object instantiated from that class. Discuss in fragments This program is a little longer than the previous programs, so I will break it down and discuss it in fragments. A complete listing of the program is shown in Listing 10. The class definition shown in Listing 6 is used to construct a custom
exception object that encapsulates a message. Note that this class extends
Exception. (Therefore, it is a checked exception.)
The constructor for this class receives an incoming String message parameter and passes it to the constructor for the superclass. This makes the message available for access by the getMessage method invoked in the catch block. The try block Listing 7 shows the beginning of the main method, including the entire
try block
The main method executes a for loop (inside the try block) that guarantees that the variable named cnt will reach a value of 3 after a couple of iterations. Once during each iteration, (until the value of cnt reaches 3)
a print statement inside the for loop displays the value of cnt.
This results in the output shown in Figure 11.
What happens when cnt equals 3? However, when the value of cnt equals 3, the throw statement highlighted in boldface in Listing 7 is executed. This causes control to transfer immediately to the matching catch block following the try block (see Listing 8). During this iteration, the print statement following the throw statement is not executed. Therefore, the output never shows a value for cnt greater than 2, as shown in Figure 11. The catch block Listing 8 shows a catch block whose type matches the type of exception
thrown in Listing 7.
When the throw statement is executed in Listing 7, control is transferred immediately to the catch block in Listing 8. No further code is executed within the try block. A reference to the object instantiated as the argument to the throw keyword in Listing 7 is passed as a parameter to the catch block. That reference is known locally by the name e inside the catch block. Using the incoming parameter The code in the catch block invokes the method named getMessage
(inherited from the Throwable class) on the incoming parameter and
displays that message on the screen. This produces the output shown in
Figure 12.
When the catch block finishes execution ... When the code in the catch block has completed execution, control is
transferred to the first executable statement following the catch block
as shown in Listing 9.
That executable statement is a print statement that produces the output shown
in Figure 13.
A complete listing of the program is shown in Listing 10.
SummaryThis lesson has covered many of the details having to do with exception handling in Java. By now, you should know that the use of exception handling is not optional in Java, and you should have a pretty good idea how to use exception handling in a beneficial way. Along the way, the discussion has included the following topics:
What's Next?For the time being, that completes the miniseries entitled "The Essence of
OOP using Java." I may decide to come back later and add some lessons
on inner classes and other similar topics, but it will probably be a while
before I get around to that. In the meantime, I sincerely hope that you
have enjoyed this miniseries, and have found the lessons useful in your
continuing effort to learn and understand OOP as implemented using Java. Copyright 2002, Richard G. Baldwin. Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited. About the authorRichard Baldwin is a college professor (at Austin Community College in Austin, Texas) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web. Richard has participated in numerous consulting projects, and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin's Programming Tutorials, which has gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine. Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems. -end- |
| Go to page: Prev 1 2 3 |
