CSC153, Class 35: When Things Go Wrong Overview: * Problems in Programs * Handling Problems * Exceptions: Java's Solutions + Calling exceptional methods + "Optional" exceptions + Throwing exceptions + Defining your own exceptions Notes: * Three of you left your exams here. Bleh. * No, Oge, homework 2 is not yet graded. * Are there questions on homework 3? * Class format: Initially discussion/recitation. Then lecture. Things Go Wrong in Procedures: Examples: * Sometimes you do a division and you might end up dividing by 0 * Sometimes you end up computing something too large (e.g., in our rational computations for inequality) * You may index incorrectly in an array * The power may go out * The hard disk may fry What do you do about these kinds of problems? * Write preconditions * Check them (may be expensive) + Crash with nice friendly complaint message + Return a special value and let the caller check the return value and handle it * Don't check them. If things go wrong, it's the caller's fault * Second model: Try thing, cross fingers, check result z = x/y; if DIVIDE_BY_ZERO_ERROR z = 1; * Often used for file opening operations Observation: Most programmers do the following: * "Let's get it out quick; I'll add error-checking later" * Never find time to go back and do the error-checking Java Language Design Goal: Make it hard for programmers to follow their incredibly lazy habits. Make them deal with errors that may occur. Exceptions - Signals that an error has occured In a method/procedure/function that may fail to operate correctly, you note that this procedure may "throw an exception" /** * Average all th values in grades. * * @param grades a list of grades. * @exception Exception if grades is empty. */ public double average(List grades) throws Exception { ... } What happens when you call an exceptional method. gradecomputer.average(grades_for_cs153_homework_2); The Java compiler will say "Good programmers always test for errors. Rewrite your code." How to say "I know this may fail miserably" try { code-that-may-fail; } catch (Exception e) { stuff-to-do-if-it-fails; } Q: When does the catch get invoked? A: Immediately after code-that-may-fail fails. Yes, it's a control structure. Q: When might you write this try/catch stuff? A: Let's look at some examples One of the problems from yesterday: Repeatedly read a password Variant: Repeatedly read a number until it's in the range 0 .. 100 public class SillyExample { public static void main(String[] args) { SimpleInput in = new SimpleInput(); SimpleOutput out = new SimpleOutput(); int grade; do { out.print("Enter a grade between 0 and 100: "); try { grade = in.readInt(); } catch (Exception e) { out.println("Please enter numbers in the format ..."); grade = 101; // So that the next test works } } while ((grade < 0) || (grade > 100)); out.println("Wow, I thougth Sam never assigned grades " + " as high as " + grade + " in his classes."); } // main(String[]) } // class SillyExample Brian observes that readInt can fail in multiple ways: * Bad prompt leads user to type "three" instead of 3. (Yes, there's a reason the grade is so low.) * The input may be closed (e.g., keyboard disconnected). We would therefore hope that the declaration of readInt looks something like public int readInt() throws BadInputException, EOFException { ... } public class SillyExample { public static void main(String[] args) { SimpleInput in = new SimpleInput(); SimpleOutput out = new SimpleOutput(); int grade; try { do { out.print("Enter a grade between 0 and 100: "); try { grade = in.readInt(); } catch (BadInputException e) { out.println("Please enter numbers in the format ..."); grade = 101; // So that the next test works } catch (EOFException e) { // Crash and Burn (throw an exception from main) // Write a nice error message and stop throw Exception("Arjun says that this shouldn't happen"); } } while ((grade < 0) || (grade > 100)); out.println("Wow, I thougth Sam never assigned grades " + " as high as " + grade + " in his classes."); } catch (Exception e) { out.println("Sorry, this program was written by Microsoft."); } } // main(String[]) } // class SillyExample Note: We don't need the catch (EOFException) because the outer catch will catch it. Suppose you really hate error checking public static void main(String[] args) throws Exception { ... } What if you don't care whether or not someone catches an error (or what if an error is not reasonably catchable)? RuntimeException You can catch them, you don't have to Error I don't think you can catch them; stop NOW!