Download 13. Exceptions

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
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.