340 likes | 361 Views
Learn about basic exception handling syntax, Java exception classes, real-world strategies, and design-time error trapping. Understand terminology, common errors, and predefined exception classes. Explore design-time error trapping and advanced error control.
E N D
Introduction To Scientific Programming Chapter 8 – Exception Handling
Lecture Overview On Exception Handling • Basic Exception Handling • Background & Terminology • Syntax • Java Exception Classes • Real-World Strategies • Design-Time Error Trapping • Un-Expected Error Control • “Anticipated” Error Control • Wrap-Up • Book Case Study • Extra Syntax
I. Exception Handling - Background • Handling errors is one of the most critical and practical aspects of programming today. • The goal of error handling – no “lock-ups”/”blow-ups” or crashes! Recover (if you can) from errors. • My theory: There are more ways for things to go wrong than right. • Some believe that you can actually write as much code for error control and recovery as the application itself.
Background (cont.) • This is an evolving area, mostly because of public outcry about the poor performance of software! • Historically, error handling has not been studied because not part of OOP “theory”. • In Java, and other “recent” languages, actual syntax and classes have been built into the language to improve error handling. • Sun is once again updating error control from the J2SE 1.4.2 SDK to J2SE 5.0!
Java “Exception Handling” • In Java, errors have been historically referred to as “Exceptions”. • The most recent version has added one more level of abstraction - “Throwable”. • Two things are built into Java: • Syntax: try-catch-finally,… • Classes: Exception, Throwable, … Java Documentation on Class Structure for Handling Errors (Oct. 2004)
Types Of Program Errors • Semantic • These happen at design-time • Syntax problems are caught by compiler (95% of the time) • Logic • These happen at both design-time and run-time • Some can be caught by complier • Examples include: typing errors, assignment mistakes, … • Run-time • These happen during program execution • Can result in program “lock-up” or “blow-up”! • Examples include: array indexing, file I/O, null pointers, math problems (division by zero),…
Exception Handling Terminology • An exception is an error or something in your program that is undefined or not suppose to happen. • Throwing an exception is wheneither Java software or your code signals that an exception has happened. • Catching an exception is the response to a thrown exception by executing a part of the program specifically written for that exception. • The Exception Class is a predefined class in Java that contains a structure and methods to work with errors.
Basic Error Handling Syntax:try-throw-catch try { <code to try> if(test condition) throw new Exception(“Error message to display"); <more code> } catch (Exception e) { <exception handling code> } <possibly more code>
Basic Error Handling Syntax (cont.) • The try block contains code that could produce an error. • The catch block handles the exception, if thrown. • The catch block takes a parameter of an error class type - .i.e. Exception, Throwable, … • This is called the catch-block parameter (e or eX are commonly used names) • If an exception is thrown, execution in the try block ends and control passes to the catch block(s) after the try. • The Exception object gets loaded with error information at the time the error occurs (run-time).
Java Predefined Exception Classes • Many classes in Java throw exceptions • Check the documentation for specific details • The exceptions thrown are often also predefined • Top-5 predefined Exception classes are: • ArrayIndexOutOfBoundsException • NullPointerException • IOException • FileNotFoundException • DivideByZeroException • Throwable is now the root class of all exceptions. • The inherited class Exception handles most to the errors produced by built-in Java code.
II. Real-World Error Handling Strategies • In a departure from your book, I will describe error control structures based on specific programming needs. • Three main error control strategies are: • Design-Time Error Trapping • Un-Expected Error Control • “Anticipated” or Application Error Control
II.A - Design-Time Error Trapping • One of the most important types of error control can be implemented during program design - before software is ever released. • Use error control structures to help trap logic and programming mistakes during the design process. • Examples of common errors include array indexing, null pointers, operating system problems, file I/O problems, etc… • One can easily add code to trap these errors and report the problem.
Design-Time Error Trapping Example try { <code to try> } catch (ArrayIndexOutOfBoundsException eX) { System.out.println("Array index error in …"); System.out.println(eX.getMessage()); <code to recover or exit> } • Simple example to catch a potential array index error. • The .getMessage method will give information on the type of error that has occurred. • No throw is necessary because code is triggering error.
Design-Time Error Trapping Example (More Features) try { <code to try> } catch (ArrayIndexOutOfBoundsException eX) { StackTraceElement[] errStack; System.out.println("Array index error in …"); System.out.println(eX.getMessage()); errStack = eX.getStackTrace(); for (int i=0;i<errStack.length;i++) { System.out.println(errStack[i]); } <code to recover or exit> } • Can printout an entire stack trace with .getStackTrace !
Design-Time Error Trapping Example (Final) try { <code to try> } catch (ArrayIndexOutOfBoundsException eX) { <code to handle Exception> } catch (NullPointerException eX) { <code to handle Exception> } catch (Exception eX) { <code to handle Exception> } • Can use multiple catches to trap a variety of errors
II-B. Uncaught Exceptions • If an exception is not caught in the method that throws it or any of its calling methods, then either the program ends, or even worse, the program may become unstable. • One solution is to wrap the program main method in try-catch block that includes a catch with the most generic error class "Throwable"
Uncaught Exceptions Example public static void main(String[] args) { try { … } … catch (Throwable eX) { System.out.println("Unexpected error in program …"); System.out.println(eX.getMessage()); } }
II.C – “Anticipated” Error Control • Applications, by their very nature, produce all sorts of conditions that are either undefined or a logical error. • Sometimes this is referred to as “application” error control. • The standard try-throw-catch syntax is designed to allow the programmer the ability to trap and handle such errors without losing control of the program. • There are generally two types of error control strategies: • Throw a predefined error • “Throw–your–own” error
#1 - Using The PredefinedDivideByZeroExceptionClass public void getUserInput() { try { System.out.println("Enter numerator:"); numerator = SavitchIn.readLineInt(); System.out.println("Enter denominator:"); denominator = SavitchIn.readLineInt(); if (denominator == 0) throw new DivideByZeroException(); quotient = (double)numerator/(double)denominator; System.out.println(numerator + "/" + denominator + " = " + quotient); } catch(DivideByZeroException eX) { System.out.println(eX.getMessage()); tryUserInPutOneMoreTime(); //One more chance for non-zero denominator } } • Catch error right at the source (and maybe attempt recovery)
#2 - “Throw-Your-Own” Error Control • There are three interesting ways to use custom error control: • Custom error control at its’ source. • Custom error control by creating your own Exception Class. • Custom error control by “juicing-up” or extending existing Exception Classes. • B. is the most work so consequently, you see it the least (unfortunately).
#2A – Custom Error Control At The Source try { <code to try> if(test condition) throw new Exception(“No records in phone list to process"); <more code> } catch (Exception eX) { System.out.println(eX.getMessage()); //prints message <customized error handling code> } <possibly more code> • Use the base Exception Class to handle a custom application error.
#2B - Custom Error Control By Defining Your Own Exception Class • This is the most general and powerful way to handle application errors. It is also the most work. • You have to: • Define your own error class (inherited from the base class Exception) • Modify the appropriate method declarations • Add a catch clause “up-stream” • Two major advantages of this approach: • Most control over program flow • Un-clutters error handling code by separating most error code into another class
Defining Your Own Exception Class public class RecordNotFound extends Exception { public RecordNotFound() //Default constructor { super("Could not find record in database!"); <add more code to handle error> } public RecordNotFound(String message) //Optional constructor { super(message); <add more code to handle error> } } • Uses Inheritance to extend the base Exception Class • Utilize the .getMessage of the base class by calling super and then add anything else that is needed. For example Display 8.3/page 417
throws-Clause With Custom Error Class (No Catch Clause) public void searchDatabase() throws RecordNotFound { <statements to define the method> if(test condition) throw new RecordNotFound("Search failed, no records found"); <more statements (no catch clause)> } • searchDatabase may throw a RecordNotFound exception in the method. • With a throws-clause in the method definition, if the Exception is thrown, Java starts the search for the catch block. • With no try-catch block (optional), the search proceeds up the stack of calling methods.
catch-Block With Custom Error Class public static void main(String[] args) { try { … } catch(RecordNotFound eX) //fatal error, exit program { System.exit(-1); } catch(Throwable eX) { System.out.println("Unexpected error in program …"); System.out.println(eX.getMessage()); } } • If RecordNotFound is thrown in method searchDatabase, execution, program searches for the catch clause up-stream from method. • Java will go all the way up to main (if necessary). • You can “bubble” up an error as far as you need.
Programming Style Issues With Exception Classes • You must include a throws-clause to declare any exception that might be thrown but is not caught in the method. • The throws-clause "passes the buck" to whatever method called it. That method can also pass the buck, but eventually some method must catch it. • Methods can throw more than one exception, separated by a comma. • catch blocks immediately following the try block are searched in sequence for one that catches the exception type. The first catch block that handles the exception type is the only one that executes. • Hence, catch the more specific exception(s) first.
Issues Withthrows-Clausesin Derived Classes • You cannot add exceptions to the throws-clause of an overridden method in a derived class • Only exceptions in the throws-clause of the parent class's method can be in the throws -clause of the overridden method in the derived class • In other words, you cannot throw any exceptions that are not either caught in a catch block or already listed in the throws -clause of the same method in the base class. • Also, all custom Exception classes (being derived from the Exception base class) must be defined in the current class or ancestor class.
#2C “Juicing Up” Or Extending Existing Exception Classes public class MyDivideByZeroException extends DivideByZeroException { public MyDivideByZeroException() { super("Dividing by Zero!"); //Call DivideByZeroException <add more code to handle error> } public MyDivideByZeroException(String message) { super(message); //Call DivideByZeroException <add more code to handle error> } } • Must be derived from an existing Exception Class. • Uses inheritance to extend basic Exception Class. For example Display 8.3/page 417
III.-A Your Book’s Case Study:A Line-Oriented Calculator • The strategy was to add error handling only after coding the main functionality (good). • They developed a custom Exception Class that is thrown when the user enters an unknown operator • They also structured a method evaluate that potentially throws an exception that is handled in main • In main, it asks the user to re-enter the calculation • It also includes an exception for division by zero.
Line-Oriented Calculator evaluate Method public double evaluate(char op, double n1, double n2) throws DivideByZeroException, UnknownOpException { ... case '+': answer = n1 + n2; break; ... case '/': if ((-precision < n2) && (n2 < precision) throw new DivideByZeroException(); answer = n1/n2; break; default: throw new UnknownOpException(op); ... } cases for – and * ops not shown here—see text for complete code Throws exception if op is any char other than +, -, *, /
Custom Exception Class UnknownOpException public class UnknownException extends Exception { public UnknownOpException() { super("UnknownOpException"); } public UnknownOpException(char op) { super (op + " is an unknown operator."); } public UnknownOpException(String message) { super(message); } } Note: all three constructors provide a way for the Exception object to have a meaningful message.
Line-Oriented Calculator main method … public static void main(String[] args) { Calculator clerk = new Calculator(); try { … } catch (UnknownOpException e) { clerk.handleUnknownOpException(e); } catch (DivideByZeroException e) { clerk.handleDivideByZeroException(e); } …
III.-B More Syntax - The finally Block • You can add a finally block after the try/catch blocks • finally blocks execute whether or not catch block(s) execute • Code organization using finally block: try block catch block finally { <Code to be executed whether or not an exception is thrown> }
Three Possibilities for a try-catch-finally Block • The try-block runs to the end and no exception is thrown. • The finally-block runs after the try-block. • An exception is thrown in the try-block and caught in the matching catch-block. • The finally-block runs after the catch-block. • An exception is thrown in the try-block and there is no matching catch-block. • The finally-block is executed before the method ends. • Code that is after the catch-blocks but not in a finally-block would not be executed in this situation.