| ## Java 1.1 Unleashed # - 7- Exception Handling by David R. Chung IN THIS CHAPTER What Is an Exception? If Exceptions Are the Answer, What Is the Question? Some Terminology Don't Throw Up Your Hands-- throw an Exception The Throwable Class Types of Exceptions Built-In Exceptions Errors are a normal part of programming. Some of these errors are flaws in a program's basic design or implementation--these are called bugs. Other types of errors are not really bugs; rather, they are the result of situations like low memory or invalid filenames. The way you handle the second type of error determines whether they become bugs. Unfortunately, if your goal is to produce robust applications, you probably find yourself spending more time handling errors than actually writing the core of your application. Java's exception-handling mechanism lets you handle errors without forcing you to spend most of your energy worrying about them. ## What Is an Exception? As the name implies, an exception is an exceptional condition. An exception is something out of the ordinary. Most often, exceptions are used as a way to report error conditions. Exceptions can be used as a means of indicating other situations as well. This chapter concentrates primarily on exceptions as an error-handling mechanism. Exceptions provide notification of errors and a way to handle them. This control structure allows you to specify exactly where to handle specific types of errors. NOTE: Other languages like C++ and Ada provide exception handling. Java's exception handling is similar to the one used by C++. ### Tennyson Understood the Problem In his poem, Charge of the Light Brigade, Andrew Lord Tennyson describes an actual battle. In this battle, a cavalry brigade is ordered to attack a gun emplacement. It turns out that the valley they attack is a trap. There are big guns on three sides, and the brave soldiers on horseback with their sabers are massacred. The poem describes an actual battle from the Crimean War. The battle as Tennyson describes it highlights a classic problem. Someone (probably far from the front) had given the order to attack. The men who led the charge became aware very quickly that an error had been made. Unfortunately, they did not have the authority to do anything about it. In Tennyson's immortal words, "Theirs not to reason why, theirs but to do and die: into the valley of Death rode the 600." Using exceptions in Java allows you to determine exactly who handles an error. In fact, low-level functions can detect errors while higher-level functions decide what to do about them. Exceptions provide a way to communicate information about errors up through the chain of methods until one of them can handle it. ## If Exceptions Are the Answer, What Is the Question? Most procedural languages like C and Pascal do not use exception handling. In these languages, a variety of techniques are used to determine whether an error has occurred. The most common means of error checking is the function's return value. Consider the problem of calculating the retail cost of an item and displaying it. For this example, the retail cost is twice the wholesale cost:
    int retailCost( int wholesale ) {
        if ( wholesale <= 0 ) {
            return 0 ;
        }
        return (wholesale * 2 ) ;
    }
The `retailCost()` method takes the wholesale price of an item and doubles it. If the wholesale price is negative or zero, the function returns zero to indicate that an error has occurred. This method can be used in an application as follows:
    int wholesalePrice = 30 ;
    int retailPrice = 0 ;
    retailPrice = retailCost( wholesalePrice ) ;
    System.out.println( "Wholesale price = " + wholesalePrice ) ;
    System.out.println( "Retail price = " + retailPrice ) ;
In this example, the `retailCost()` method calculates the correct retail cost and prints it. The problem is that the code segment never checks whether the `wholesalePrice` variable is negative. Even though the method checks the value of `wholesalePrice` and reports an error, there is nothing that forces the calling method to deal with the error. If this method is called with a negative `wholesalePrice` value, the function blindly prints invalid data. Therefore, no matter how diligent you are in ensuring that your methods return error values, the callers of your methods are free to ignore them. You can prevent bad values from being printed by putting the whole operation in a method. The `showRetail()` method takes the wholesale price, doubles it, and prints it. If the wholesale price is negative or zero, the method does not print anything and returns the `boolean` value `false`:
    boolean showRetail( int wholesale ) {
        if ( wholesale <= 0 ) {
            return false ;
        }
        int retailPrice ;
        retailPrice = wholesalePrice * 2 ;
        System.out.println( "Wholesale price = " + wholesale ) ;
        System.out.println( "Retail price = "    + retailPrice ) ;
        return true ;
    }
Using this new and improved method guarantees that bad values are never printed. However, once again, the caller does not have to check to see whether the method returned `true`. The fact that the caller can choose to ignore return values is not the only problem with using return values to report errors. What happens if your method returns a `boolean` and both `true` and `false` are valid return values? How does this method report an error? Consider a method to determine whether a student passes a test. The `pass()` method takes the number of correct answers and the number of questions. The method calculates the percentage; if it is greater than 70 percent, the student passes. Consider the `passingGrade()` method:
    boolean passingGrade( int correct, int total ) {
        boolean returnCode = false ;
        if ( (float)correct / (float)total > 0.70 ) {
            returnCode = true ;
        }
    return returnCode ;
    }
In this example, everything works fine as long as the method arguments are well behaved. What happens if the number correct is greater than the total? Or worse, if the total is zero (because this causes a division by zero in the method.) By relying on return values in this case, there is no way to report an error in this function. Exceptions prevent you from making your return values do double duty. Exceptions allow you to use return values to return only useful information from your methods. Exceptions also force the caller to deal with errors--because exceptions cannot be ignored. ## Some Terminology Exception handling can be viewed as a nonlocal control structure. When a method throws an exception, its caller must determine whether it can catch the exception. If the calling method can catch the exception, it takes over and execution continues in the caller. If the calling method cannot catch the exception, the exception is passed on to its caller. This process continues until either the exception is caught or the top (or bottom, depending on how you look at it) of the call stack is reached and the application terminates because the exception has not been caught. Java exceptions are class objects subclassed from `java.lang.Throwable`. Because exceptions are class objects, they can contain both data and methods. In fact, the base class `Throwable` implements a method that returns a `String` describing the error that caused the exception. This is useful for debugging and if you want to give users a meaningful error message. ## Don't Throw Up Your Hands-- throw an Exception The `passingGrade()` method presented in the preceding section was unable to report an error condition because all its possible return values were valid. Adding exception handling to the method makes it possible to uncouple the reporting of results from the reporting of errors. The first step is to modify the `passingGrade()` method definition to include the `throws` clause. The `throws` clause lists the types of exceptions that can be thrown by the method. In the following revised code, the method throws only an exception of type `Exception`:
    static boolean passingGrade( int correct, int total )
                                        throws Exception {

        boolean returnCode = false ;
The rest of the method remains largely unchanged. This time, the method checks to see whether its arguments make sense. Because this method determines passing grades, it would be un- reasonable to have more correct responses than total responses. Therefore, if there are more correct responses than total responses, the method throws an exception. The method instantiates an object of type `Exception`. The `Exception` constructor takes a `String` parameter. The string contains a message that can be retrieved when the exception is caught. The `throw` statement terminates the method and gives its caller the opportunity to catch it:
    if( correct > total ) {
            throw new Exception( "Invalid values" ) ;
        }
        if ( (float)correct / (float)total > 0.70 ) {
            returnCode = true ;
        }
        return returnCode ;
    }
## throw, try, and catch Blocks To respond to an exception, the call to the method that produces it must be placed within a `try` block. A `try` block is a block of code beginning with the `try` keyword followed by a left and right curly brace. Every `try` block is associated with one or more `catch` blocks. Here is a `try` block:
    try
        {
        // method calls go here
        }
If a method is to catch exceptions thrown by the methods it calls, the calls must be placed within a `try` block. If an exception is thrown, it is handled in a `catch` block. Different `catch` blocks handle different types of exceptions. This is a `try` block and a `catch` block set up to handle exceptions of type `Exception`:
    try
        {
        // method calls go here
        }
    catch( Exception e )
        {
        // handle exceptons here
        }
When any method in the `try` block throws any type of exception, execution of the `try` block ceases. Program control passes immediately to the associated `catch` block. If the `catch` block can handle the given exception type, it takes over. If it cannot handle the exception, the exception is passed to the method's caller. In an application, this process goes on until a `catch` block catches the exception or the exception reaches the `main()` method uncaught and causes the application to terminate. ### An Exceptional Example Because all Java methods are class members, the `passingGrade()` method is incorporated in the `gradeTest` application class. Because `main()` calls `passingGrade()`, `main()` must be able to catch any exceptions `passingGrade()` might throw. To do this, `main()` places the call to `passingGrade()` in a `try` block. Because the `throws` clause lists type `Exception`, the `catch` block catches the `Exception` class. Listing 7.1 shows the entire `gradeTest` application. #### Listing 7.1. The gradeTest application.
    import java.io.* ;
    import java.lang.Exception ;
    public class gradeTest {
        public static void main( String[] args ) {
            try
                {
                // the second call to passingGrade throws
                // an excption so the third call never
                // gets executed
                System.out.println( passingGrade( 60,  80 ) ) ;
                System.out.println( passingGrade( 75,   0 ) ) ;
                System.out.println( passingGrade( 90, 100 ) ) ;
                }
            catch( Exception e )
                {
                System.out.println( "Caught exception --" +
                                    e.getMessage() ) ;
                }
        }
        static boolean passingGrade( int correct, int total )
                                            throws Exception {
            boolean returnCode = false ;
            if( correct > total ) {
                throw new Exception( "Invalid values" ) ;
            }
            if ( (float)correct / (float)total > 0.70 ) {
                returnCode = true ;
            }
            return returnCode ;
        }
    }
The second call to `passingGrade()` fails in this case because the method checks to see whether the number of correct responses is less than the total responses. When `passingGrade()` throws an exception, control passes to the `main()` method. In this example, the `catch` block in `main()` catches the exception and prints `Caught exception - Invalid values`. ### Multiple catch Blocks In some cases, a method may have to catch different types of exceptions. Java supports multiple `catch` blocks. Each `catch` block must specify a different type of exception:
    try
        {
        // method calls go here
        }
    catch( SomeExceptionClass e )
        {
        // handle SomeExceptionClass exceptions here
        }
    catch( SomeOtherExceptionClass e )
        {
        // handle SomeOtherExceptionClass exceptions here
    }
When an exception is thrown in the `try` block, it is caught by the first `catch` block of the appropriate type. Only one `catch` block in a given set will be executed. Notice that the `catch` block looks a lot like a method declaration. The exception caught in a `catch` block is a local reference to the actual exception object. You can use this exception object to help determine what caused the exception to be thrown in the first place. ### Does Every Method Have to Catch Every Exception? What happens if a method calls another method that throws an exception but chooses not to catch it? In the example in Listing 7.2, `main()` calls `foo()`, which in turn calls `bar()`. `bar()` lists `Exception` in its `throws` clause; because `foo()` is not going to catch the exception, it must also have `Exception` in its `throws` clause. The application in Listing 7.2 shows a method, `foo()`, that ignores exceptions thrown by the called method. #### Listing 7.2. A method that ignores exceptions thrown by the method it calls.
    import java.io.* ;
    import java.lang.Exception ;
    public class MultiThrow {
        public static void main( String[] args ) {
            try
                {
                foo() ;
                }
            catch( Exception e )
                {
                System.out.println( "Caught exception " +
                                    e.getMessage() ) ;
                }
        }
        static void foo() throws Exception {
            bar() ;
        }
        static void bar() throws Exception {
            throw new Exception( "Who cares" ) ;
        }
    }
In the example in Listing 7.3, `main()` calls `foo()` which calls `bar()`. Because `bar()` throws an exception and doesn't catch it, `foo()` has the opportunity to catch it. The `foo()` method has no `catch` block, so it cannot catch the exception. In this case, the exception propagates up the call stack to `foo()`'s caller, `main()`. #### Listing 7.3. A method that catches and rethrows an exception.
    import java.io.* ;
    import java.lang.Exception ;
    public class MultiThrow {
        public static void main( String[] args ) {
            try
                {
                foo() ;
                }
            catch( Exception e )
                {
                System.out.println( "Caught exception " +
                                    e.getMessage() ) ;
                }
        }
        static void foo() throws Exception {
            try
                {
                bar() ;
                }
            catch( Exception e )
                {
                System.out.println( "Re throw exception -- " +
                                    e.getMessage() ) ;
                throw e ;
                }    }
        static void bar() throws Exception {
            throw new Exception( "Who cares" ) ;
        }
    }
The `foo()` method calls `bar()`. The `bar()` method throws an exception and `foo()` catches it. In this example, `foo()` simply rethrows the exception, which is ultimately caught in the application's `main()` method. In a real application, `foo()` could do some processing and then rethrow the exception. This arrangement allows both `foo()` and `main()` to handle the exception. ### The finally Clause Java introduces a new concept in exception handling: the `finally` clause. The `finally` clause sets apart a block of code that is always executed. Here's an example of a `finally` clause:
    import java.io.* ;
    import java.lang.Exception ;
    public class MultiThrow {
        public static void main( String[] args ) {
            try
                {
                alpha() ;
                }
           catch( Exception e }
                {
                System.out.println( "Caught exception " ) ;
                }
           finally()
                {
                System.out.println( "Finally. " ) ;
                }
        }
    }
In normal execution (that is, when no exceptions are thrown), the `finally` block is executed immediately after the `try` block. When an exception is thrown, the `finally` block is executed before control passes to the caller. If `alpha()` throws an exception, it is caught in the `catch` block and then the `finally` block is executed. If `alpha()` does not throw an exception, the `finally` block is executed after the `try` block. If any code in a `try` block is executed, the `finally` block is executed as well. ## The Throwable Class All exceptions in Java are subclassed from the class `Throwable`. If you want to create your own exception classes, you must subclass `Throwable`. Most Java programs do not have to subclass their own exception classes. Following is the `public` portion of the class definition of `Throwable`:
    public class Throwable {
        public Throwable() ;
        public Throwable(String message) ;
        public String getMessage()
        public String toString() ;
        public void printStackTrace() ;
        public void printStackTrace(
                            java.io.PrintStream s) ;
        private native void printStackTrace0(
                            java.io.PrintStream s);
        public native Throwable fillInStackTrace();
    }
The constructor takes a string that describes the exception. Later, when an exception is thrown, you can call the `getMessage()` method to get the error string that was reported. ## Types of Exceptions The methods of the Java API and the language itself also throw exceptions. These exceptions can be divided into two classes: `Exception` and `Error`. Both the `Exception` and `Error` classes are derived from `Throwable`. `Exception` and its subclasses are used to indicate conditions that may be recoverable. `Error` and its subclasses indicate conditions that are generally not recoverable and that should cause your applet to terminate. The various packages included in the Java Development Kit throw different kinds of `Exception` and `Error` exceptions, as described in the following sections. ### java.awt Exceptions The AWT classes have members that throw one error and two exceptions: `AWTException` (exception in AWT) `llegalComponentStateException` (a component is not in the proper state for a requested operation) `AWTErr` (error in AWT) ### java.awt.datatransfer Exception Classes of the AWT data transfer package may throw this exception: `UnsupportedFlavorException` (data in improper format) NOTE: In the JDK 1.1 data transfer model, Java uses the word Flavor in place of the more common term Format. ### java.beans Exceptions The classes of the `java.beans` package throw the following exceptions: `IntrospectionException` (unable to resolve object during introspection) `PropertyVetoException` (illegal property change) ### java.io Exceptions The classes in the `java.io` package throw a variety of exceptions, as shown in Table 7.1 and Figure 7.1. Any classes that work with I/O are good candidates to throw recoverable exceptions. For example, activities such as opening files or writing to files are likely to fail from time to time. The classes of the `java.io` package do not throw errors at all. #### Table 7.1. The java.io exceptions.
Exception | Cause
`CharConversionException` | Root class for character conversion exceptions
`IOException` | Root class for I/O exceptions
`EOFException` | End of file
`FileNotFoundException` | Unable to locate file
`InterruptedIOException` | I/O operation was interrupted; contains a member `bytesTransferred` that indicates how many bytes were transferred before the operation was interrupted
`InvalidClassException` | Class is not valid for serialization
`InvalidObjectException` | Class explicitly forbids serialization
`NotActiveException` | Serialization not active
`NotSerializableException` | Class may not be serialized
`ObjectStreamException` | Root class for object stream exceptions
`OptionalDataException` | Contains data members to indicate end of file or optional data to read
`StreamCorruptedException` | Stream fails internal consistency test
`SyncFailedException` | Synchronization failed
`UTFDataFormatException` | Malformed UTF-8 string
`UnsupportedEncodingException` | Character-encoding mechanism not supported
`WriteAbortException` | Exception in stream
Figure 7.1. The `java.io` exception hierarchy. ### java.lang Exceptions The `java.lang` package contains much of the core Java language. The exceptions subclassed from `RuntimeException` do not have to be declared in a method's `throws` clause. These exceptions are considered normal because nearly any method can throw them. Table 7.2 and Figure 7.2 show the recoverable exceptions from the `java.lang` package. Table 7.3 and Figure 7.3 show the nonrecoverable errors in the `java.lang` package. #### Table 7.2. The java.lang exceptions.
Exception | Cause
`ArithmeticException` | Arithmetic error condition (for example, divide by zero)
`ArrayIndexOutOfBoundsException` | Array index less than zero or greater than actual size of array
`ArrayStoreException` | Object type mismatch between array and object to be stored in array
`ClassCastException` | Cast of object to inappropriate type
`ClassNotFoundException` | Unable to load requested class
`CloneNotSupportedException` | Object does not implement cloneable interface
`Exception` | Root class of exception hierarchy
`IllegalAccessException` | Class is not accessible
`IllegalArgumentException` | Method received illegal argument
`IllegalMonitorStateException` | Improper monitor state (thread synchronization)
`IllegalStateException` | Method invoked at improper time
`IllegalThreadStateException` | Thread is in improper state for requested operation
`IndexOutOfBoundsException` | Index is out of bounds
`InstantiationException` | Attempt to create instance of abstract class
`InterruptedException` | Thread interrupted
`NegativeArraySizeException` | Array size less than zero
`NoSuchFieldException` | Attempt to access invalid field
`NoSuchMethodException` | Unable to resolve method
`NullPointerException` | Attempt to access `null` object member
`NumberFormatException` | Unable to convert string to number
`RuntimeException` | Base class for many `java.lang` exceptions
`SecurityException` | Security settings do not allow operation
`StringIndexOutOfBoundsException` | Index is negative or greater than size of string
#### Table 7.3. The java.lang errors.
Error | Cause
`AbstractMethodError` | Attempt to call abstract method
`ClassCircularityError` | This error is no longer used
`ClassFormatError` | Invalid binary class format
`Error` | Root class of error hierarchy
`ExceptionInInitializerError` | Unexpected exception in initializer
`IllegalAccessError` | Attempt to access inaccessible object
`IncompatibleClassChangeError` | Improper use of class
`InstantiationError` | Attempt to instantiate abstract class
`InternalError` | Error in interpreter
`LinkageError` | Error in class dependencies
`NoClassDefFoundError` | Unable to find class definition
`NoSuchFieldError` | Unable to find requested field
`NoSuchMethodError` | Unable to find requested method
`OutOfMemoryError` | Out of memory
`StackOverflowError` | Stack overflow
`ThreadDeath` | Indicates that thread will terminate; can be caught to perform clean up (if caught, must be rethrown)
`UnknownError` | Unknown virtual machine error
`UnsatisfiedLinkError` | Unresolved links in loaded class
`VerifyError` | Unable to verify bytecode
`VirtualMachineError` | Root class for virtual machine errors
Figure 7.2. The `java.lang` exception hierarchy. ### java.lang.reflect Exception The classes of `java.lang.reflect` throw the following exception: `InvocationTargetException` (invoked method has thrown an exception) Figure 7.3. The `java.lang` error hierarchy. ### java.net Exceptions The `java.net` package handles network communications. Its classes most often throw exceptions to indicate connect failures and the like. Table 7.4 and Figure 7.4 show the recoverable exceptions from the `java.net` package. The classes of the `java.net` package do not throw errors at all. #### Table 7.4. The java.net exceptions.
Exception | Cause
`BindException` | Unable to bind socket--port in use
`ConnectException` | Remote socket refused connection--no listening socket
`MalformedURLException` | Unable to interpret URL
`NoRouteToHostException` | Unable to reach host--firewall in the way
`ProtocolException` | Socket class protocol error
`SocketException` | Socket class exception
`UnknownHostException` | Unable to resolve host name
`UnknownServiceException` | Connection does not support service
Figure 7.4. The `java.net` exception hierarchy. ### java.rmi Error The Java Remote Method Invocation classes allow Java objects to exist on remote machines. These classes throw the following error: `ServerError` (remote server indicates error) ### java.rmi Exceptions Java objects whose methods are invoked remotely through RMI may throw exceptions. Table 7.5 and Figure 7.5 show the exceptions thrown from the `java.rmi` package. #### Table 7.5. The java.rmi exceptions.
Exception | Cause
`AccessException` | Operation not allowed
`AlreadyBoundException` | Name is already bound
`ConnectException` | Host refused connection
`ConnectIOException` | I/O exception during connection
`MarshalException` | Error during marshaling
`NoSuchObjectException` | Object no longer exists
`NotBoundException` | Name is not bound
`RMISecurityException` | `RMISecurityManager` throws exception
`RemoteException` | Invalid remote method
`ServerException` | Remote server throws exception
`ServerRuntimeException` | Remote server throws runtime exception
`StubNotFoundException` | Remote object not exported
`UnexpectedException` | Unknown error
`UnknownHostException` | Exception not in method signature
`UnmarshalException` | Error in unmarshaling; possible stream corruption
### java.rmi.server Exceptions RMI servers throw exceptions. Table 7.6 shows these `java.rmi.server` exceptions. Figure 7.5. The `java.rmi` exception hierarchy. #### Table 7.6. The java.rmi.server exceptions.
Exception | Cause
`ExportException` | Port in use
`ServerCloneException` | Unable to clone
`ServerNotActiveException` | Server not executing remote method
`SkeletonMismatchException` | Stub and skeleton do not match
`SkeletonNotFoundException` | Skeleton not found or invalid
`SocketSecurityException` | Attempt to use invalid port
### java.security Exceptions The Java security API allows users to implement security features in Java. The API includes support for digital signatures, data encryption, key management, and access control. Table 7.7 and Figure 7.6 show the exceptions thrown from the `java.security` package. #### Table 7.7. The java.security exceptions.
Exception | Cause
`DigestException` | Generic digest error
`InvalidKeyException` | Key invalid
`InvalidParameterException` | Actual method parameter invalid
`KeyException` | Generic key error
`KeyManagementException` | Key management system error
`NoSuchAlgorithmException` | Algorithm does not exist
`NoSuchProviderException` | Security provider is not available
`ProviderException` | Security provider exception
`SignatureException` | Generic signature error
Figure 7.6. The `java.security` exception hierarchy. ### java.security.acl Exceptions The Java security access control list API allows Java developers to control access to specific users. The classes of `java.security.acl` throw the following exceptions: `ACLNotFoundException` (unable to find access control list) `LastOwnerExcepti` (attempt to delete last owner of ACL) `NotOwnerExcepti` (only the owner may modify) ### java.sql Exceptions The Java SQL API throws the following exceptions: `DataTruncation` (unexpected data truncation) `SQLException` (SQL error--contains detailed SQL information) `SQLWarning` (SQL warning) ### java.text Exception The Java text API throws the following exception: `FormatException` (format or parsing error) ### java.util Exceptions The classes of the `java.util` package throw the following exceptions: `EmptyStackException` (no objects on stack) `MissingResourceException` (resource missing) `NoSuchElementExcepti`on (no more objects in collection) `TooManyListenersExcepti`on (thrown by unicast event listeners) NOTE: Unicast is Java terminology for a singleton server object. Singletons are objects that can be instantiated only once. ### java.utils.zip Exceptions The Java utilities zip API throws the following exceptions: `DataFormatException` (format error) `ZipException` (Zip error) ## Built-In Exceptions In the example in Listing 7.4, you see how the automatic exceptions in Java work. This application creates a method and forces it to divide by zero. The method does not have to explicitly throw an exception because the division operator throws an exception when required. #### Listing 7.4. An example of a built-in exception.
    import java.io.* ;
    import java.lang.Exception ;
    public class DivideBy0 {
        public static void main( String[] args ) {
        int a = 2 ;
        int b = 3 ;
        int c = 5 ;
        int d = 0 ;
        int e = 1 ;
        int f = 3 ;
        try
            {
            System.out.println( a+"/"+b+" = "+div( a, b ) ) ;
            System.out.println( c+"/"+d+" = "+div( c, d ) ) ;
            System.out.println( e+"/"+f+" = "+div( e, f ) ) ;
            }
        catch( Exception except )
            {
            System.out.println( "Caught exception " +
                                    except.getMessage() ) ;
            }
        }
        static int div( int a, int b ) {
            return (a/b) ;
        }
    }
The output of this application is shown here:
    2/3 = 0
    Caught exception / by zero
The first call to `div()` works fine. The second call fails because of the divide-by-zero error. Even though the application did not specify it, an exception was thrown--and caught. So you can use arithmetic in your code without writing code that explicitly checks bounds. ## Summary The exception-handling mechanism in Java allows your methods to report errors in a manner that cannot be ignored. Every exception that is thrown must be caught, or the application terminates. Exceptions are actually class objects derived from the `Throwable` class. Therefore, exceptions combine data and methods; an exception object generally contains a string explaining what the error is. Exception handling helps you combine error processing in one place. It uncouples the reporting of results and the reporting of errors. If you use exception handling, you can create much more powerful and robust code.
| ©Copyright, Macmillan Computer Publishing. All rights reserved.