Tues. Nov. 25 An exception is an unexpected error or condition, such as ◦ You issue a command to read a file from a disk, but the file does not exist there ◦ You attempt to write data to a disk, but the disk is full or unformatted ◦ Your program asks for user input, but the user enters invalid data ◦ The program attempts to divide a value by 0 These are the object-oriented methods to manage such errors Java has two basic classes of errors: Error and Exception Both of these classes descend from the Throwable class, as shown next Object ◦ Throwable Exception IOException Runtime Exception ArithmeticException IndexOutOfBoundsException ArrayIndexOutOfBoundsException Others Error VirtualMachineError OutofMemoryError InternalError Others… These are serious errors from which your program cannot recover Such as, a misspelled class name or a class stored in the wrong folder If the program cannot find the class, an Error condition occurs If the program runs out of memory, an Error condition occurs These are less serious errors that represent unusual conditions that arise while the program is running and from which the program can recover Examples include using an invalid array subscript or performing certain illegal arithmetic operations Your program can determine the type of error by examining the code of the error returned by Java C:\Java\Java xyz.java error: cannot read xyz.java 1 error C:\Java\>_ In this case there is no program code you could write that could fix or prevent the error message When the program generates an exception message, it produces a different type of message An exception message is one that could have been prevented by writing specific methods in the program Consider the following program… public class MathMistake { public static void main(String[] args) { int num = 13, denom = 0, result; result = num / denom; } } C:\Java\java MathMistake Exception in thread “main” java.lang.ArithmeticException: / by zero at MathMistake.main<MathMistake.java:6> C:\Java>_ The Exception is a java.lang.ArithmeticException which is one of many subclasses of Exception You are told the type of error as well as the line number of the error You can simply let the program terminate The termination is abrupt and unforgiving This might annoy the user Or the termination could be disastrous such as in an air traffic control situation Consider the following arithmetic (division by 0) error and its various traditional ways of handling the error public class MathMistake { public static void main(String[] args) { int num = 13, denom = 0, result; if(denom == 0) System.exit(1); result = num / denom; } } When you use System.exit(), the current application ends and control returns to the operating system The convention is to return a value of 1 if an error is causing the termination; otherwise, a value of 0 is returnedunder normal termination Using System.exit() circumvents displaying the error message shown above because the program ends before the the division by zero occurs When you write code to detect exceptions, you ‘try’ a procedure that might cause an error A method that detects an exception ‘ throws an exception,’ and the block of code that processes the error ‘catches the exception.’ Programs that can handle exceptions are said to be more fault tolerant and robust ◦ Fault-tolerant apps are designed so that they continue to operate, possibly at a reduced level When you create a segment of code in which something might go wrong, you place the code in a try block, which is a block of code you attempt to execute while acknowledging that an exception might occur The keyword catch An opening parenthesis An Exception type A name for an instance of the Exception type A closing parenthesis An opening curly brace The statements that take the action you want A closing curly brace returnType methodName(optional arguments) { optional statements prior to code that is tried try { //statements that might generate an exception } catch(Exception someException) { // actions to take if exception occurs } // optional statements that occur after try } In the slide above, someException represents an object of the Exception class or any of its subclasses If an exception occurs during the execution of the try block, the statements in the catch block execute If no exception occurs within the try block, the catch block does not execute Either way the statements following the catch block execute normally public class MathMistakeCaught { public static void main(String[] args) { int num = 13, denom = 0, result; try { result = num / denom; } catch(ArithmeticException mistake) { System.out.println("Attempt to divide by zero!"); } } } C:\Java>java MathMistakeCaught Attempt to divide by zero! C:\Java> If you want to send error messages to a different location from ‘normal’ you can use System.err instead of System.out Lots of different types of errors could have occurred within the try block You can have the system print the type of error with the following code public class MathMistakeCaught2 { public static void main(String[] args) { int num = 13, denom = 0, result; try { result = num / denom; } catch(ArithmeticException mistake) { System.out.println(mistake.getMessage()); } } } Uses the getMessage() method to generate the message that ‘comes with’ the caught ArithmeticException argument to the catch block C:\Java>java MathMistakeCaught2 / by zero C:\Java>_ try { result = num / denom; } catch(ArithmeticException mistake) { result = num/1; System.out.println(mistake.getMessage()); } Holds a valid value—either the code in the try block worked, or the code in the catch block assigned a valid value to result if the try block did not work The catch blocks are written so that they look like methods You can place as many statements as you need within a try block and you can catch as man Exceptions as you want However, the first such Exception will cause the logic to leave the try block and to enter the catch block Thus, the first error-generating statement throws an Exception When a program contains multiple catch blocks, they are examined in sequence until a match is found for the type of Exception that occurred Then, the matching catch block executes and each remaining catch block is bypassed For example, consider the code below public class TwoMistakes { public static void main(String[] args) { int num[] = {4, 0, 0}; try { num[2] = num[0] / num[1]; num[2] = num[3] / num[0]; } catch(ArithmeticException e) { System.out.println("Arithmetic error"); } catch(IndexOutOfBoundsException e) { System.out.println("Out of bounds error"); } System.out.println("End of program"); } } C:\Java\java TwoMistakes Arithmetic error End of program C:\Java>_ Note that the second statement in the try block is never attempted and the second catch block is skipped public class TwoMistakes2 { public static void main(String[] args) { int num[] = {4, 0, 0}; try { num[2] = num[0] / 10; num[2] = num[3] / num[0]; } catch(ArithmeticException e) { System.out.println("Arithmetic error"); } catch(IndexOutOfBoundsException e) { System.out.println("Out of bounds error"); } System.out.println("End of program"); } } C:\Java\java TwoMistakes2 Out of bounds error End of program C:\Java>_ Again, the try block is abandoned, the first catch block is examined and found unsuitable because it does not catch an IndexOutOfBoundsException The program proceeds to the second catch block The following program uses only one catch block to catch both ArithmeticExceptions and IndexOutOfBounds exceptions The above exceptions are both subclasses of Exception Therefore, the catch blocks shown above can be replaced with a single generic catch block, as shown below public class TwoMistakes3 { public static void main(String[] args) { int num[] = {4, 0, 0}; try { num[2] = num[0] / num[1]; num[2] = num[3] / num[0]; } catch( Exception e) { System.out.println(e.getMessage()); } } } Will catch all exceptions When either an arithmetic exception or array index exception occurs, the thrown exception is ‘promoted’ to an Exception error in the catch block Because an Exception is Throwable, you can use the Throwable class getMessage() method If you place a generic catch block first and then specific catch blocks afterwards, the specific catch blocks will possess code that is unreachable because the generic catch block will catch all exceptions before they can be tested against specific catch blocks Unreachable code statements are program statements that can never execute under any circumstances. Try blocks should not throw more than four exception types finally blocks follow catch blocks and are used to cleanup after try and catch blocks regardless of whether an exception occurred or not Try { // statements of try } catch(Exception e) { // actions taken if exception was thrown } finally { // actions taken whether catch block executed or not } There is a System.exit(); statement in either the try block or the catch block An unplanned Exception occurs When an unplanned Exception occurs, the application is stopped and control is returned to the operating system where the Exception is handled—the program is abandoned try { // Open the file // Read the file // Place the file data in an array // Calculate an average from the data // Display the average } catch(IOException e) { // Issue an error message // System exit } finally { // if file is open, close it } The advantage of exception handling is that it enables you to create a fix-up for the exception and to permit the program to continue It also simplifies exception handling overall call methodA() If methodA() worked { call methodB() if methodB() worked { call methodC() if methodC() worked Everything is OK so print final result else Set errorCode to ‘C’ } else Set errorCodee to ‘B” } else Set errorCode to ‘A’ } try { call methodA() and maybe throw an exception call methodB() and maybe throw an exception call methodC() and maybe throw an exception } Catch(methodA()’s error) { set errorCode to ‘A’ } Catch(methodB()’s error) { set errorCode to ‘B’ } Catch(methodC()’s error) { set errorCode to ‘C’ } Logic is much simplier Reusability of the method is much better If a method throws an exception that will not be caught inside the method, you must use the keyword throws followed by an Exception type in the method header Consider the following code… Public class PriceList { private static final double[] price = {15.99,27.88,34.56,45.89}; public static void displayPrice(int item) throws IndexOutOfBoundsException { System.out.println(“The price is” + price[item]; } } public class PriceListApplication1 { public static void main(String[] args) { int item = 4; try { PriceList.displayPrice(item); } catch(IndexOutOfBoundsException e) { System.out.println("Price is $0"); } } } import javax.swing.*; public class PriceListApplication2 { public static void main(String[] args) { int item = 4; try { PriceList.displayPrice(item); } catch(IndexOutOfBoundsException e) { while(item < 0 || item > 3) { String answer = JOptionPane.showInputDialog(null, "Please reenter a value 0, 1, 2 or 3"); item = Integer.parseInt(answer); } PriceList.displayPrice(item); } System.exit(0); } } Java’s exceptions come in two types: ◦ Checked exceptions—the type programmers should be detecting and recovering from ◦ Unchecked exceptions—don’t mess with these Programmers usually cannot anticipate unchecked exceptions, which are ◦ Hardware failures ◦ Logic errors ◦ [programs cannot fix these] Programs can only fix checked exceptions while it is executing All exceptions that you specifically throw are checked exceptions These descend from the Exception class These are not runtime exceptions Catch it in the method Declare the exception in your method header’s throws clause If you use the latter, then any programmer who uses your method must do one of the following: ◦ Catch and handle the exception ◦ Declare the exception in the throws clause of their method The method’s return type The type and number of arguments the method requires The type and number of Exceptions the method throws Why don’t you have to know what other methods the method extends from and what other methods the method implements? When an exception occurs, Java will trace back through the call stack looking for a catch in each of the methods If none is found, control returns to the operating system Consider the following program… import javax.swing.*; public class DemoStackTrace { public static void main(String[] args) { methodA(); // line 6 } public static void methodA() { System.out.println("In methodA()"); methodB(); // line 11 } public static void methodB() { System.out.println("In methodB()"); methodC(); // line 16 } public static void methodC() { System.out.println("In methodC()"); JFrame frame = null; frame.setVisible(true); // line 22 } } C:\Java>java DemoStackTrace In methodA() In methodB() In methodC() Exception in thread “main” java.lang.nullPointerException at DemoStrackTrace.methodC(DemoStackTrace.java:22) at DemoStrackTrace.methodB(DemoStackTrace.java:16) at DemoStrackTrace.methodA(DemoStackTrace.java:11) at DemoStrackTrace.main(DemoStackTrace.java:6) C:\Java> import javax.swing.*; public class DemoStackTrace2 { public static void main(String[] args) { methodA(); // line 6 } public static void methodA() { System.out.println("In methodA()"); try { methodB(); // line 13 } catch(RuntimeException e) { System.out.println("In methodA() - The stack trace:"); e.printStackTrace(); } System.out.println("Method ends normally."); System.out.println("Application could continue here."); } public static void methodB() { System.out.println("In methodB()"); methodC(); // line 26 } public static void methodC() { System.out.println("In methodC()"); JFrame frame = null; frame.setVisible(true); // line 32 } } C:\Java>java DemoStackTrace In methodA() In methodB() In methodC() In methodA() – The stack trace: java.lang.nullPointerException at DemoStrackTrace.methodC(DemoStackTrace.java:32) at DemoStrackTrace.methodB(DemoStackTrace.java:26) at DemoStrackTrace.methodA(DemoStackTrace.java:13) at DemoStrackTrace.main(DemoStackTrace.java:6) Method ends normally. Application could continue here. C:\Java> Java provides over 40 categories of Exceptions that you can use in your programs But Java cannot anticipate all of the possible exceptions you might want to catch ◦ Ex. A negative bank balance ◦ Ex. Someone tries to access your email To create your own throwable Exception, you must extend a subclass of Throwable. The class Throwable has two subclasses— Exception and Error Exception() – constructs a new exception with null as its detail message Exception(String message) – constructs a new exception with the specified detail message Exception(String message, Throwable cause) – constructs a new exception with the specified detail message and cause Exception(Throwable cause) – constructs a new exception with the specified cause public class HighBalanceException extends Exception { public HighBalanceException() { super("Customer balance is high"); } } public class CustomerAccount { private int acctNum; private double balance; public static double HIGH_CREDIT_LIMIT = 20000.00; public CustomerAccount(int num, double bal) throws HighBalanceException { acctNum = num; balance = bal; if(balance > HIGH_CREDIT_LIMIT) throw(new HighBalanceException()); } } import javax.swing.*; public class UseCustomerAccount { public static void main(String[] args) { int num; double balance; String input; input = JOptionPane.showInputDialog(null, "Enter account number"); num = Integer.parseInt(input); input = JOptionPane.showInputDialog(null, "Enter balance due"); balance = Double.parseDouble(input); try { CustomerAccount ca = new CustomerAccount(num, balance); JOptionPane.showMessageDialog(null, "Customer #" + num + " has a balance of $" + balance); } catch( HighBalanceException hbe) { JOptionPane.showMessageDialog(null, "Customer #" + num + " has a balance higher than the credit limit"); } System.exit(0); } } Assertions are Java language features that help you detect logic errors that do not create runtime errors, but do produce results that are wrong You use assert statement to create an assertion The syntax is… Assert booleanExpression : optionalErrorMessage import javax.swing.*; class PayRaise { public static void main(String[] args) { double oldPay = 0; double newPay = 0; final double INCREASE = 0.04; final double TAXRATE = 0.28; final double HRSPERWEEK = 40; final double INSURANCE = 140.00; String entry; entry = JOptionPane.showInputDialog(null, "Enter old pay per hour"); oldPay = Double.parseDouble(entry); newPay = oldPay + oldPay * INCREASE; assert oldPay < newPay: "\nOld Pay is " + oldPay + "\nNew pay is $" + newPay + "\nNew pay should be more than old pay"; newPay = (newPay * HRSPERWEEK) (newPay * TAXRATE) - INSURANCE; assert oldPay < newPay: "Old Pay is " + oldPay + "\nNew pay is $" + newPay + "\nNew pay should be more than old pay"; JOptionPane.showMessageDialog(null, "New net pay is $" + newPay + " per week"); System.exit(0); } } C:\Java>javac –source 1.6 PayRaise.java C:\Java>java –ea Payraise Exception in thread “main” java.lang.AssertioniError: Old Pay is $12.48 New pay is $0.0 New pay should be more than old pay At PayRaise.main<PayRaise.java:18> C:\Java> public class CustomerAccount { private int acctNum; private double balance; public static double HIGH_CREDIT_LIMIT = 20000.00; public CustomerAccount(int num, double bal) throws HighBalanceException { acctNum = num; balance = bal; if(balance > HIGH_CREDIT_LIMIT) throw(new HighBalanceException()); } } import javax.swing.*; public class DemoStackTrace { public static void main(String[] args) { methodA(); // line 6 } public static void methodA() { System.out.println("In methodA()"); methodB(); // line 11 } public static void methodB() { System.out.println("In methodB()"); methodC(); // line 16 } public static void methodC() { System.out.println("In methodC()"); JFrame frame = null; frame.setVisible(true); // line 22 } }