|
|
|
Advertisement
|
Catching exceptions
To catch an exception in Java, you write a try block with one or more
catch clauses. Each catch clause specifies one exception type that it
is prepared to handle. The try block places a fence around a bit of
code that is under the watchful eye of the associated catchers. If the
bit of code delimited by the try block throws an exception, the
associated catch clauses will be examined by the Java virtual machine.
If the virtual machine finds a catch clause that is prepared to handle
the thrown exception, the program continues execution starting with the
first statement of that catch clause.
As an example, consider a program that requires one argument on the
command line, a string that can be parsed into an integer. When you
have a String and want an int, you can invoke
the parseInt() method of the Integer class.
If the string you pass represents an integer, parseInt()
will return the value. If the string doesn't represent an integer,
parseInt() throws NumberFormatException. Here
is how you might parse an int from a command-line
argument:
// In Source Packet in file except/ex1/Example1.java
class Example1 {
public static void main(String[] args) {
int temperature = 0;
if (args.length > 0) {
try {
temperature = Integer.parseInt(args[0]);
}
catch(NumberFormatException e) {
System.out.println(
"Must enter integer as first argument.");
return;
}
}
else {
System.out.println(
"Must enter temperature as first argument.");
return;
}
// Create a new coffee cup and set the temperature of
// its coffee.
CoffeeCup cup = new CoffeeCup();
cup.setTemperature(temperature);
// Create and serve a virtual customer.
VirtualPerson cust = new VirtualPerson();
VirtualCafe.serveCustomer(cust, cup);
}
}
Here, the invocation of parseInt() sits inside a try
block. Attached to the try block is a catch clause that catches
NumberFormatException:
catch(NumberFormatException e) {
System.out.println(
"Must enter integer as first argument.");
return;
}
The lowercase character e is a reference to the thrown
(and caught) NumberFormatException object. This reference
could have been used inside the catch clause, although in this case it
isn't. (Examples of catch clauses that use the reference are shown
later in this article.)
If the user types Harumph as the first argument to the
Example1 program, parseInt() will throw a
NumberFormatException exception and the catch clause will
catch it. The program will print:
Must enter integer as first argument.
Although the above example had only one catch clause, you can have many
catch clauses associated with a single try block. Here's an example:
// In Source Packet in file except/ex1/VirtualCafe.java
class VirtualCafe {
public static void serveCustomer(VirtualPerson cust,
CoffeeCup cup) {
try {
cust.drinkCoffee(cup);
System.out.println("Coffee is just right.");
}
catch (TooColdException e) {
System.out.println("Coffee is too cold.");
// Deal with an irate customer...
}
catch (TooHotException e) {
System.out.println("Coffee is too hot.");
// Deal with an irate customer...
}
}
}
If any code inside a try block throws an exception, its catch clauses
are examined in their order of appearance in the source file. For
example, if the try block in the above example throws an exception, the
catch clause for TooColdException will be examined first,
then the catch clause for TooHotException. During this
examination process, the first catch clause encountered that handles
the thrown object's class gets to "catch" the exception. The ordering
of catch-clause examination matters because it is possible that
multiple catch clauses of a try block could handle the same exception.
catch clauses indicate the type of abnormal condition they handle by
the type of exception reference they declare. In the example above, the
catch clauses declare exception type TooColdException and
TooHotException. Had a single catch clause declared a
TemperatureException, a thrown
TooColdException or TooHotException still
would have been caught, because TemperatureException is
the superclass of both these classes. In the object-oriented way of
thinking, a TooColdException is a
TemperatureException, therefore, a catch clause for
TemperatureException also will catch a thrown
TooColdException. An example of this is shown below:
// In Source Packet in file except/ex2/VirtualCafe.java
class VirtualCafe {
public static void serveCustomer(VirtualPerson cust,
CoffeeCup cup) {
try {
cust.drinkCoffee(cup);
System.out.println("Coffee is just right.");
}
catch (TemperatureException e) {
// This catches TooColdException, TooHotException,
// as well as TemperatureException.
System.out.println("Coffee is too cold or too hot.");
// Deal with an irate customer...
}
}
}
Multiple catch clauses could handle the same exception because you may,
for example, declare two catch clauses, one for
TooColdException and another for
TemperatureException. In this case, however, you must
place the catch clause for TooColdException above the one
for TemperatureException, or the source file won't
compile. If a catch clause for TemperatureException could
be declared before a catch clause for TooColdException,
the first catch clause would catch all TooColdExceptions,
leaving nothing for the second catch clause to do. The second catch
clause would never be reached. The general rule is: subclass catch
clauses must precede superclass catch clauses. Here's an example of
both orders, only one of which compiles:
// In Source Packet in file except/ex3/VirtualCafe.java
class VirtualCafe {
public static void serveCustomer(VirtualPerson cust,
CoffeeCup cup) {
try {
cust.drinkCoffee(cup);
System.out.println("Coffee is just right.");
}
catch (TemperatureException e) {
// This catches TooColdException, TooHotException,
// as well as TemperatureException.
System.out.println("Coffee is too cold or too hot.");
// Deal with an irate customer...
}
// THIS WON'T COMPILE, BECAUSE THIS catch clause
// WILL NEVER BE REACHED.
catch (TooColdException e) {
System.out.println("Coffee is too cold.");
}
}
}
// In Source Packet in file except/ex4/VirtualCafe.java
// This class compiles fine.
class VirtualCafe {
public static void serveCustomer(VirtualPerson cust,
CoffeeCup cup) {
try {
cust.drinkCoffee(cup);
System.out.println("Coffee is just right.");
}
catch (TooColdException e) {
System.out.println("Coffee is too cold.");
// Deal with an irate customer...
}
catch (TemperatureException e) {
// This catches TooHotException as well
// as TemperatureException.
System.out.println(
"There's temperature trouble in this coffee.");
// Deal with an irate customer...
}
}
}
|
Sponsored Links
|