Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
13. Exceptions To Err is Computer, To Forgive is Fine – Dr. Who Exceptions are errors that are generated while a computer program is running. Such errors are called run-time errors. These types of errors are different from the errors that the compiler generates (called compile-time errors). Compile-time errors are generated in response to erroneous syntax in the source code. Run-time errors are generated in response to erroneous semantics. For example, it is not a compile-time error to divide by zero, but it is a run-time error. 13.1 Generating your first exception Suppose you want to divide two numbers. If you cause the computer to divide by zero, an exception will be thrown at run-time: public class ExceptionExample { public static void main(String args[]) { System.out.println( "f(0)=" + f(0)); } public static int f(int x) { return 1/x; } } This generates the following run-time error: Exception in thread "main" java.lang.ArithmeticException: / by zero at ExceptionExample.f(ExceptionExample.java) at ExceptionExample.main(ExceptionExample.java) Copyright 2001, DocJava, Inc. 188 Java for Programmers 13.2 Intercepting the Run-time Error We intercept the error before it occurs. This is called guarding the input. For example, we could say: public static int f(int x) { if (x == 0) return 0; return 1/x; } But this would return an invalid answer for a bad input (which is actually much worse than stopping the program and informing the user). To intercept an exception, after it has been thrown, you use a try-catch block: public class ExceptionExample { public static void main(String args[]) { try { System.out.println( "f(0)=" + f(0)); } catch (ArithmeticException e) { System.out.println("Bad input for f!"); } System.out.println("program continues..."); } public static int f(int x) { return 1/x; } } This outputs: Bad input for f! program continues... We see that the program does not stop suddenly, when dividing by zero. When a run-time error occurs, according to the Java Language Specification [Gosling], the Java machine will throw an exception. When an exception is thrown, a non-local transfer of control occurs from the area that generated the exception to a place that can catch the exception. In our case, we caught the exception, emitted an error Copyright 2001, DocJava, Inc. Java for Programmers message, and then allowed the program to continue. The interesting part about this approach is that we can select where the error handling occurs, and protect the program from bombing during a mission-critical area of the code. 13.3 Defining your own Exception Suppose you are interested in building a credit card processing routine. You want the routine to perform an elementary check on the credit card number, and if there is a problem, it throws an exception. When our check finds a problem, a new exception is thrown called a CreditCardException. Here is how we define it: public class CreditCardException extends Exception { public CreditCardException(String s) { super (s); } public static void check(int i) throws CreditCardException { if (i < 0) { throw new CreditCardException( "credit card ="+i); } } } The Exception class is defined in the java.lang package. A new exception may be defined by sub-classing the Exception class. The class that does the credit card check only checks to make sure that the credit card is positive. However, this is an implementation detail, and a more complete credit card check could easily be performed. Here is a class that checks the credit card: public class CheckCreditCard { public static void main(String args[]) { try { CreditCardException.check(-9); } catch (CreditCardException e) { e.printStackTrace(); System.out.println("Heres the cc exception"); return ; } System.out.println("done."); } } Copyright 2001, DocJava, Inc. 189 190 Java for Programmers 13.4 Checked and Unchecked Exceptions There are two kinds of exceptions, checked and unchecked. When a method is invoked that throws a checked exception, then the invoking method must place the invocation in a try-catch block, or declare it in the throws clause. For example: public static void check(int i) { CreditCardException.check(-9); } Causes a compile-time error: Error : Exception CreditCardException must be caught, or it must be declared in the throws clause of this method. ExceptionExample.java line 41 CreditCardException.check(9); Thus, we have two possible actions, declare the CreditCardException in the throws clause: public static void check(int i) throws CreditCardException { CreditCardException.check(-9); } Or we can place the invocation inside a try-catch block: public static void check(int i) { try { CreditCardException.check(-9); } catch (CreditCardException e) { e.printStackTrace(); } } The checked is defined by sub-classing the Exception class. The unchecked exception is defined by sub-classing the RuntimeException class. With an unchecked exception, No try-catch construct is needed to invoke methods or Copyright 2001, DocJava, Inc. Java for Programmers 191 statements that throw RuntimeExceptions. For example, dividing by zero can throw a RuntimeException. Figure 13.4-1 shows the java.lang Exception subclass hierarchy. java.lang.ClassNotFoundException java.lang.CloneNotSupportedException java.lang.IllegalAccessException java.lang.Throwable java.lang.Exception java.lang.InstantiationException java.lang.InterruptedException java.lang.NoSuchMethodException java.lang.RuntimeException Figure 13.4-1. An overview of the java.lang exception classes A zoom in of the java.lang.RuntimeException class hierarchy is shown in Figure 13.4-2. java.lang.ArithmeticException java.lang.ArrayStoreException java.lang.ClassCastException java.lang.IllegalArgumentException java.lang.Exception java.lang.RuntimeException java.lang.IllegalMonitorStateException java.lang.IndexOutOfBoundsException java.lang.NegativeArraySizeException java.lang.NullPointerException java.lang.SecurityException Figure 13.4-2. An overview of the java.lang.RuntimeException classes Copyright 2001, DocJava, Inc. 192 Java for Programmers 13.5 The MBNF for the t r y statement The Modified Backus Naur Form (MBNF) for the try-catch block is: tryStatement "try" statement < "catch" "(" parameter ")" statement > [ "finally" statement] . It is typical to use the try-catch block with any code that might fail. As seen with the division example, given above, there was no requirement for the try-catch block. Thus, there was no requirement that the code be able to handle run-time errors locally. A typical pattern for the try-catch block follows: try { . . . } catch ( . . . ) { . . . } catch ( . . . ) { . . . } . . . For example: try { // create an instance of your applet class a = (Applet) Class.forName(className).newInstance(); } catch (ClassNotFoundException e) { System.out.println( "ClassNotFoundException in AppletFrame"); return ; } catch (InstantiationException e) { System.out.println( "InstantiationException in AppletFrame"); return ; } catch (IllegalAccessException e) { System.out.println( "IllegalAccessException in AppletFrame"); return ; } Copyright 2001, DocJava, Inc. Java for Programmers When an exception is caught, a message is obtainable as an instance of a string, using: e.getMessage() A sophisticated program might log the messages from the exceptions (called error logging) so that proper steps can be taken to correct the error. At the other extreme, we could catch the exceptions and then continue running, ignoring all exceptions. For example: try { out.write(buffer); } catch (Exception e) { } A new exception is defined by extending the Exception class. For example: class FileFormatException extends Exception { public FileFormatException(String s) { super (s); } Try catch blocks can slow down the execution of code slightly. They create a local scope of variables. It is therefore important to place exceptions at the right level of granularity. It would not be appropriate to, for example, place every division inside of a try-catch block. It would be better practice to program by assertion. Programming by assertion protects the input to a method so that it is reasonable and unlikely to cause an exception. The checked exception decends from the Exception class. Such exceptions do require a try-catch statement, or are required to be in methods that throw a checked exception. For example: public class ThrowsExample { public static void main(String args[]) { Float value = Float.valueOf("1.0"); System.out.println(value); value = Float.valueOf("blah blah blah"); System.out.println(value); } } Copyright 2001, DocJava, Inc. 193 194 Java for Programmers Will output: 1.0 _exceptionOccurred: java.lang.NumberFormatException (blah blah blah) java.lang.NumberFormatException: blah blah blah at java.lang.Float.valueOf(Float.java) at ThrowsExample.main(TrivialApplication.java) at com.apple.mrj.JManager.JMStaticMethodDispatcher.run(JMA WTContextImpl.java) at java.lang.Thread.run(Thread.java) The java.lang.NumberFormatException is an unchecked or RuntimeException, sine the NumberFormatException subclasses the IllegalArgumentException, which subclasses the RuntimeException. With checked exceptions, the try-catch block is required. For example: public class FileExample { public static File openFile() { return new File("foo.txt"); } public static FileReader openFileReader() { return new FileReader(openFile()); } public static void main(String args[]) { System.out.println(openFileReader()); } } Will not compile. The syntax error is: Error : Exception java.io.FileNotFoundException must be caught, or it must be declared in the throws clause of this method. TrivialApplication.java line 23 return new FileReader(openFile()); The following shows a way to fix the code: public class FileExample { public static File openFile() { return new File("foo.txt"); } public static FileReader openFileReader() throws FileNotFoundException { Copyright 2001, DocJava, Inc. Java for Programmers return new FileReader(openFile()); } public static void main(String args[]) { try { System.out.println(openFileReader()); } catch (FileNotFoundException e) { e.printStackTrace(); } } } In summary, 1. An exception is a run-time condition. 2. Exceptions can be thrown by any instance of a class that subclasses java.lang.Throwable. 3. Exceptions must be caught in order to be intercepted and processed. 4. A try-catch block can be used to process exceptions 5. The finally clause is always executed. 6. Checked exceptions subclass the Exception class. 7. Unchecked exceptions subclass the RuntimeException class. 13.6 Exercises 1. A Master card number is a positive integer that has 16 digits. Design a credit card checking routine that throws a CreditCardException when the number of digits in the credit card is invalid. 2. Write a program that computes how much it costs to leave a computer on 24 hours a day, 7 days a week. Assume that the computer uses 0.2 KW/Hr and that power costs 10 cents per KW-Hr. Tabulate the costs of operating a computer as a function of the cost of power. In crease the cost of power by 5 cents per Kw-Hr until you get to 50 cents per Kw-Hr. Use a function to perform the computation. Make the cost of power and total amount of power consumed parameters. If the Copyright 2001, DocJava, Inc. 195 196 Java for Programmers parameters are negative, throw an InvalidPowerException. Make this a RuntimeException so that try-catch blocks are not required. Copyright 2001, DocJava, Inc.