Exception Handling Recitation – 10/(23,24)/2008 CS 180 Department of Computer Science, Purdue University Announcements Project 6 is out 2 week project Milestone Due October 29, 10:00pm Final Submission Due November 5, 10:00pm This is the date of Exam 2, so start early on the project! Introduction An exception is an object Signals the occurrence of unusual event during program execution Every program should handle possible exceptions. Throw an exception when something goes wrong. Catch the exception – handle the unusual event. Why do we need exception handling ? Recover from errors! Consider this simple program: import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner keyboard = new Scanner(System.in); System.out.println("Please enter a number:"); int number = keyboard.nextInt(); System.out.println(number); } } What if the user types ”fifteen” ? The program crashes with InputMismatchException Test Class (with appropriate exception handling) import java.util.Scanner; import java.util.InputMismatchException; public class Test { public static int DEFAULT_NUMBER = 5; public static void main(String[] args) { Scanner keyboard = new Scanner(System.in); System.out.println("Please enter a number:"); int number; try{ //code where something could go wrong number = keyboard.nextInt(); } catch(InputMismatchException e){ //code executed if an InputMismatchException is thrown number = DEFAULT_NUMBER; System.out.println("Bad input!!! Setting the number to default value, “+ number); } System.out.println(number); } } Test Class (Handling multiple exceptions) A try-catch statement can have multiple catch blocks to handle multiple possible exceptions. Example public class Test { public static void main(String args[]) { int number, divisor, quotient; try{ number = keyboard.nextInt(); System.out.println("Please enter the divisor:"); divisor = keyboard.nextInt(); //The user can enter an illegal value here quotient = number/divisor; //The user could have entered 0 for divisor! } catch (InputMismatchException e){ number = divisor = DEFAULT_NUMBER; System.out.println("Bad input!!! Setting the default value, “ + number); } catch (ArithmeticException e){ System.out.println(“Division by zero”); } } } Handling multiple exceptions If an exception occurs at the first line of the try block, the control transfers to the corresponding catch block. This causes code to be skipped. Solutions: If there is a way to handle exception without a try-catch block, use it. Example – check for divisor being 0 before dividing. This is the best way to deal with problems. For each statement, form a different try-catch block and catch every possible exception. Handling multiple exceptions When an exception is thrown in a try block, the catch blocks are checked in order for the matching exception It is crucial that order goes from specific exception (subclass) to general exception (parent class) since the first matching catch is executed. Compile Error Scanner keyboard = new Scanner(System.in); try{ int inverse = 1/keyboard.nextInt(); } catch (Exception e){ Parent Class e.printStackTrace(); Sub-class of } catch (InputMismatchException e){ Exception System.out.println(e.getMessage()); } The flow of control will never go into the last catch block since all the exceptions will be caught by the first catch block. This causes a compile error. These two catch blocks should be swapped. Defining Your Own Exception Classes For handling problems of a specific type, it is better to design a specific exception class rather than using the Exception class. Must be a derived class of some predefined exception class, e.g Exception, InputMismatchException etc. Example: a more specific exception class for division by 0. class DivideByZeroException extends ArithmeticException { public DivideByZeroException() { super("Dividing by Zero!"); } public DivideByZeroException(String message) { super(message); } } 9 Implementing New Exception Classes Defining your own exception class just gives you the ability to throw and catch objects of that class. Catch handlers are not part of the user-defined exception classes In other words you should explicitly indicate in your program when to throw your own exception Example: try { if (divisor == 0) throw new DivideByZeroException(“The divisor is zero”); } catch(DivideByZeroException e) { System.out.println(e.getMessage(); } An example with multiple user-defined exception classes Here’s a simple program that distributes a number of eggs into some baskets equally. public class Test { public static void main(String[] args) { Scanner keyboard = new Scanner(System.in); try{ System.out.println("Please enter the number of eggs:"); int numberOfEggs = keyboard.nextInt(); System.out.println("Please enter the number of baskets:"); int numberOfBaskets = keyboard.nextInt(); if(numberOfEggs < 0 || numberOfBaskets < 0) throw new NegativeNumberException(“Number of eggs/baskets cannot be negative”); if(numberOfBaskets==0) throw new DivideByZeroException(“No baskets?”); ….. } catch(DivideByZeroException e) { …… } catch(NegativeNumberException e) { …… } } } Accounting for Exceptions An exception can be caught in a catch block within a method definition. Alternatively, the possibility of an exception can be declared at the start of the method definition by placing the exception-class name in a throws clause. e.g int quotient(int dividend, int divisor) throws DivideByZeroException { …. } The method quotient might throw a DivideByZeroException object in its body but not handle it in a try-catch block. All this tells the compiler is that any method that calls quotient(..) is responsible for handling the thrown exception. Accounting for Exceptions Example – int quotient(int dividend, int divisor) throws DivideByZeroException { if(divisor==0) throw new DivideByZeroException(); return dividend/divisor; } int main(String args[]) { try { int q = quotient(3, 0); } //catching exception where the method is called catch(DivideByZeroException e) { System.out.println(e.getMessage()); } } Accounting for Exceptions Exceptions are thrown in one method and handled in another Multiple methods calling the same function can handle errors differently. Some method in the calling hierarchy should handle the exception main() a() b() c() If method c() declares that it throws an exception, then method b() can either catch it or pass the buck in turn. If an exception is thrown, but never caught, the program terminates. Keep It Simple Handling exceptions in the same method where they are thrown makes things too specific. If the way the exception is to be handled depends on the calling method, let the calling method handle the exception This is a good programming practice. throws Clause Not Allowed in actionPerformed A throws clause cannot be added to method actionPerformed in any action listener class. Any exception thrown in the method actionPerformed must be caught within. Quiz Scanner keyboard = new Scanner(System.in); int number = 0; try{ number = 10/ keyboard.nextInt()-keyboard.nextInt(); } catch (ArithmeticException e){ number = 8; } catch (InputMismatchException e) { number = 3; } Assume a user tries to enter 0 first, then “five”. What is the value of number at the end?