|
Ch. 9. Exception Handling |
Session 9
|
An Exception is an abnormal event that is occurs during the execution of a program. The the exception is not handled, it halts execution and causes the program to abort. This week, we learn how to "handle" exceptions, so that execution can continue if we want, and so the user experiences something more graceful than a crash. Ideally, the exception should provide some information for debugging or technical support.

Note: the crash is the result of using what we might call the default exception handler, which is the JVM. The JVM handles an exception by (a) halting execution and (b) printing a stack trace that indicates what the problem was and where the problem occurred. In this case, at runtime we tried to allocated an invalid amount of space for an array at line 8.
If we handle errors using Java's built-in try/catch mechanism, exceptions can occur without necessarily blocking program execution. (You might even be able to recover from the exception. For example, you might prompt the end-user to enter valid data.) The try block contains whatever might cause a problem. The catch block contains the behavior to execute if and when such a problem occurs.
You can create your own custom exception type.

Exception handling is built into the architecture of the Java language. Insofar
as every exception is a subclass of java.lang.Exception,
exception handling provides a good example of how the object-oriented paradigm is
fundamental to the language.
Sun's tutorial: http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html
|
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Throwable.html java.lang.Throwable is the superclass for both Error and Exception |
|
| In Java terminology, an Error
is something beyond the programmer's control and something the programmer
should not try to handle. http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Error.html |
An Exception is a
potential problem that your application should consider. http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Exception.html |
The default java.lang package defines both the
Exception class and the Error class. When the exception condition
occurs,
the virtual machine can construct an
object of type Exception . This
object inherits methods from its superclass, Throwable, that are useful for
diagnosis the problem.
Both
Error and
Exception inherit from
Throwable (that is,
they can occur at runtime), and Throwable
inherits from
Object.
Throwable provides methods that are common to
errors and exceptions (re-use code!), such as getCause()
and toString().
As a programmer, you prepare for the possibility of an exception by writing coded to handle the exception.
The architects of Java considered some exceptions to be so foreseeable that Java automatically handles them.. A better name might be: "automatically handled exceptions". Because Java handles these exceptions automatically, the compiler does not check to see whether you handle them in YOUR code:
The following example is for an unchecked exception: divide by zero.

The mechanism to handle Exception objects involves two keywords: try and catch.

Note that e.toString() is possible because every Exception object inherits from the class Throwable.
In the following excerpt, each catch clause is defined to handle a different type of runtime Exception object.

The output above occurred because no command-line arguments were given at runtime, which causes a divide-by-zero exception on line 7.
If instead at runtime there are three (3) command-line arguments, the output shows a different exception because line 11 tries to access the 42nd element in an array that only has 3 elements:
The keyword throws indicates that this method can throw an exception that it does not handle. In such a case, another method, such as the caller, should handle the exception. The compiler might force you to declare which error a method throws if you are working with the io package.

In this case, the unhandled exception in line 5 is propagated up the call
stack to the caller, which in this case is the main method, which calls the
throwOne method on line 10.
An unhandled exception is always propagated up the call stack until it is
handled or reaches its caller.
You can have a superclass handle a group of exceptions that get thrown up to the
superclass from a group of subclasses.
The location of exception handling is flexible in Java.
Here is another example that "throws" an exception (a custom exception), and it has a "finally" block (described in the following section): CallStackExampleWithCustomException3.java
The finally block executes whether or not an exception is thrown in the try block.
You might want a method to do some cleanup, such as close a database connection or a file buffer, whether or not an exception occurs.

The compiler checks to see if you handle the following kinds of exceptions in the rare case that the compiler expects your code is likely to cause these exceptions:
Because Exception is an exposed class, you can subclass it (customize it) for your needs. Java provides specific Exceptions for the core APIs, but only domain programmers know which domain objects and Exceptions they need.

To review, all Exceptions are a subclass of Throwable: http://java.sun.com/j2se/1.4.1/docs/api/java/lang/Throwable.html
This allows for code re-use and default behavior. If
Throwablewere an interface, Exceptions would not inherit default
behavior, such as GetStackTrace
http://java.sun.com/j2se/1.4.1/docs/api/java/lang/Throwable.html#getStackTrace()
and toString
http://java.sun.com/j2se/1.4.1/docs/api/java/lang/Throwable.html#toString()
In Java, objects of type Error are beyond the programmer's control, and Error objects also inherit the default behavior of Throwable.
Some Exceptions are built into Java's API specification. For example, the
ArithmeticException occurs if a program tries to
divide a number by zero.
http://java.sun.com/j2se/1.4.1/docs/api/java/lang/ArithmeticException.html
You can have a catch statement for each type of exception.

To ensure that a specialized exception is handled, make its catch block precede the catch block of its superclass. Otherwise, the more general superclass will handle the subclass exceptions, and you lose the ability to ever get to the specialized exception.

The compiler complains:
ExcDemo5.java:20: exception
java.lang.ArrayIndexOutOfBoundsException has already been caught
catch (ArrayIndexOutOfBoundsException exc)

You can have inner try blocks for specialized errors, and reserve the outmost try block for the error handling to use if all the previous attempts fail.

To create your custom exception class, you extend Java's Exception class. As always, you need to create an exception object, and your catch block must provide a reference to the exception object.

Another example:

The following program reads from a file by using the read method of the Java io package. The first line of the program is the import statement that gives this application access to all the members of the io package. Which two exceptions does the following program handle?
If I give a file name as a command-line argument, the program prints to the screen the contents of the file:
An exception is a non-normal condition that your code handles in a catch block. A finally block is for clean-up code that you want to happen at the end of method execution whether or not an Exception is thrown. Generally speaking, an exception can be thrown during execution of a try block. The finally block executes after execution leaves the try block, whether the cause of executing leaving the try block is no Exception was thrown and all the try block code has completed it execution, or an Exception was thrown and execution immediately left the try block.
Checked exceptions are certain Exceptions that that the compiler expects you, as programmer, to catch. These include input/output exceptions (IO Exceptions), NoSuchMethodException, ClassNotFoundException, and others listed in Table 9-3 (p. 355) of the textbook. If the method you defined MIGHT throw one of the checked exceptions AND the method does not have a Catch block for that exception, then the method must declare that is capable of throwing the exception:
void myMethod() throws NoSuchMethodException { ... }
This tells the Java Virtual Machine that if NoSuchMethodException is thrown during the execution of myMethod(), then the JVM should look for a catch block in the method that calls myMethod(), which might be main().
On the other hand, unchecked Exceptions are something that the compiler does not care about. For example, it is your choice whether to have a catch block for ArithmeticException [for divide by zero], ArrayIndexOutOfBoundsException [reference to an element beyond the length of the array], NegativeArraySizeException [setting the length to less than zero]. The compiler does not force you to handle these exceptions. If you do not write a catch block for the unchecked Exceptions, the JVM will automatically return the Exception message as the application fails (crashes). Other unchecked exceptions are listed in Table 9-2 (p.354).

Output is:
size = 3
length is: 3
size = 2
length is: 2
size = 1
length is: 1
size = 0
length is: 0
size = -1
ThomasException has been thrown.
ThomasException is ThomasException
Stack trace next
ThomasException
at DemoThomasExceptionSpecial.main(DemoThomasExceptionSpecial.java:25)
size = -2
Negative array java.lang.NegativeArraySizeException
Stack trace next
java.lang.NegativeArraySizeException
at DemoThomasExceptionSpecial.main(DemoThomasExceptionSpecial.java:27)
Let's look at how to catch an input/output exception when we want to read from a file.


All exceptions inherit from Throwable, so let's review Throwable
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Throwable.html
The Throwable class is the superclass of all errors and
exceptions in the Java language. Only objects that are instances of this class
(or one of its subclasses) are thrown by the Java Virtual Machine or can be
thrown by the Java throw statement. Similarly, only this class or
one of its subclasses can be the argument type in a catch clause.
Instances of two subclasses,
Error and
Exception, are conventionally used to indicate that exceptional
situations have occurred. Typically, these instances are freshly created in the
context of the exceptional situation so as to include relevant information (such
as stack trace data).
===============
Throwable provides two methods I want to point out:
public String getMessage() // returns the detail message string of this Throwable instance (which may be null).
public String toString()
Throwable
object was created with a non-null detail message string, then the result is
the concatenation of three strings:
getMessage()
method for this object If this
Throwable object was created with a
null
detail message string, then the name of the actual class of this object is
returned.
===============
Let's look at Error
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Error.html
An Error is a subclass of Throwable that indicates
serious problems that a reasonable application should not try to catch. Most
such errors are abnormal conditions. The ThreadDeath error, though
a "normal" condition, is also a subclass of Error because most
applications should not try to catch it.
===============
Let's look at Exception
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Exception.html
The class Exception and its subclasses are a form of
Throwable that indicates conditions that a reasonable application might
want to catch.
===============
System.out.println(" The exception message is " +
e.getMessage() + " and the exception string is " + e.toString());
===============
When an exception occurs, the JVM normally prints out a stack trace. A stack trace can help you debug your code. It indicates what happened before the exception occurred. It can be useful for debugging because it indicates the series of method calls, and even specific lines of execution, the precede the exception being thrown.

try
{
if (coverage2.equals("liability"))
{
liabilityFlag = true;
liabilityPremium = premium2;
}
else if (coverage2.equals("physicalDamage"))
{
physicalDamageFlag = true;
physicalDamagePremium = premium2;
}
else
throw new CoverageException (coverage2);
}
catch (CoverageException e)
{
System.out.println("EXCEPTION is " + e.toString());
}