Learning Resources
 

Throw and throws

Specifying the Exceptions Thrown by a Method

The previous section showed how to write an exception handler for the writeListmethod in the ListOfNumbersclass. Sometimes, it's appropriate for code to catch exceptions that can occur within it. In other cases, however, it's better to let a method further up the call stack handle the exception. For example, if you were providing the ListOfNumbersclass as part of a package of classes, you probably couldn't anticipate the needs of all the users of your package. In this case, it's better to not catch the exception and to allow a method further up the call stack to handle it.

If the writeListmethod doesn't catch the checked exceptions that can occur within it, the writeListmethod must specify that it can throw these exceptions. Let's modify the original writeListmethod to specify the exceptions it can throw instead of catching them. To remind you, here's the original version of the writeListmethod that won't compile.

// Note: This method won't compile by design!
public void writeList() {
    PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));
    for (int i = 0; i < SIZE; i++) {
        out.println("Value at: " + i + " = " + vector.elementAt(i));
    }
    out.close();
}

To specify that writeListcan throw two exceptions, add a throwsclause to the method declaration for the writeListmethod. The throwsclause comprises the throwskeyword followed by a comma-separated list of all the exceptions thrown by that method. The clause goes after the method name and argument list and before the brace that defines the scope of the method; here's an example.

public void writeList() throws IOException, ArrayIndexOutOfBoundsException {

Remember that ArrayIndexOutOfBoundsExceptionis an unchecked exception; including it in the throwsclause is not mandatory. You could just write the following.

public void writeList() throws IOException {

How to Throw Exceptions

Before you can catch an exception, some code somewhere must throw one. Any code can throw an exception: your code, code from a package written by someone else such as the packages that come with the Java platform, or the Java runtime environment. Regardless of what throws the exception, it's always thrown with the throwstatement.

As you have probably noticed, the Java platform provides numerous exception classes. All the classes are descendants of the Throwableclass, and all allow programs to differentiate among the various types of exceptions that can occur during the execution of a program.

You can also create your own exception classes to represent problems that can occur within the classes you write. In fact, if you are a package developer, you might have to create your own set of exception classes to allow users to differentiate an error that can occur in your package from errors that occur in the Java platform or other packages.

You can also create chained exceptions. For more information, see the Chained Exceptions section.

The throw Statement

All methods use the throwstatement to throw an exception. The throwstatement requires a single argument: a throwable object. Throwable objects are instances of any subclass of the Throwableclass. Here's an example of a throwstatement.

throw someThrowableObject;

Let's look at the throwstatement in context. The following popmethod is taken from a class that implements a common stack object. The method removes the top element from the stack and returns the object.

public Object pop() {
    Object obj;

    if (size == 0) {
        throw new EmptyStackException();
    }

    obj = objectAt(size - 1);
    setObjectAt(size - 1, null);
    size--;
    return obj;
}

The popmethod checks to see whether any elements are on the stack. If the stack is empty (its size is equal to 0), popinstantiates a new EmptyStackExceptionobject (a member of java.util) and throws it. The Creating Exception Classes section in this chapter explains how to create your own exception classes. For now, all you need to remember is that you can throw only objects that inherit from the java.lang.Throwableclass.

Note that the declaration of the popmethod does not contain a throwsclause. EmptyStackExceptionis not a checked exception, so popis not required to state that it might occur.

Throwable Class and Its Subclasses

The objects that inherit from the Throwableclass include direct descendants (objects that inherit directly from the Throwableclass) and indirect descendants (objects that inherit from children or grandchildren of the Throwableclass). The figure below illustrates the class hierarchy of the Throwableclass and its most significant subclasses. As you can see, Throwablehas two direct descendants: Errorand Exception.

The Throwable class and its most significant subclasses.

 

The Throwable class.

Error Class

When a dynamic linking failure or other hard failure in the Java virtual machine occurs, the virtual machine throws an Error. Simple programs typically do not catch or throw Errors.

Exception Class

Most programs throw and catch objects that derive from the Exceptionclass. An Exceptionindicates that a problem occurred, but it is not a serious system problem. Most programs you write will throw and catch Exceptions as opposed to Errors.

The Java platform defines the many descendants of the Exceptionclass. These descendants indicate various types of exceptions that can occur. For example, IllegalAccessExceptionsignals that a particular method could not be found, and NegativeArraySizeExceptionindicates that a program attempted to create an array with a negative size.

One Exceptionsubclass, RuntimeException, is reserved for exceptions that indicate incorrect use of an API. An example of a runtime exception is NullPointerException, which occurs when a method tries to access a member of an object through a nullreference. The section Unchecked Exceptions — The Controversy discusses why most applications shouldn't throw runtime exceptions or subclass RuntimeException.

Chained Exceptions

An application often responds to an exception by throwing another exception. In effect, the first exception causes the second exception. It can be very helpful to know when one exception causes another. Chained Exceptions help the programmer do this.

The following are the methods and constructors in Throwablethat support chained exceptions.

Throwable getCause()
Throwable initCause(Throwable)
Throwable(String, Throwable)
Throwable(Throwable)

The Throwableargument to initCauseand the Throwableconstructors is the exception that caused the current exception. getCausereturns the exception that caused the current exception, and initCausesets the current exception's cause.

The following example shows how to use a chained exception.

try {

} catch (IOException e) {
    throw new SampleException("Other IOException", e);
}

In this example, when an IOExceptionis caught, a new SampleExceptionexception is created with the original cause attached and the chain of exceptions is thrown up to the next higher level exception handler.

Accessing Stack Trace Information

Now let's suppose that the higher-level exception handler wants to dump the stack trace in its own format.


Definition: A stack trace provides information on the execution history of the current thread and lists the names of the classes and methods that were called at the point when the exception occurred. A stack trace is a useful debugging tool that you'll normally take advantage of when an exception has been thrown.

The following code shows how to call the getStackTracemethod on the exception object.

catch (Exception cause) {
    StackTraceElement elements[] = cause.getStackTrace();
    for (int i = 0, n = elements.length; i < n; i++) {       
        System.err.println(elements[i].getFileName()
            + ":" + elements[i].getLineNumber() 
            + ">> "
            + elements[i].getMethodName() + "()");
    }
}

 

Logging API

The next code snippet logs where an exception occurred from within the catchblock. However, rather than manually parsing the stack trace and sending the output to System.err(), it sends the output to a file using the logging facility in the java.util.loggingpackage.

try {
    Handler handler = new FileHandler("OutFile.log");
    Logger.getLogger("").addHandler(handler);
    
} catch (IOException e) {
    Logger logger = Logger.getLogger("package.name"); 
    StackTraceElement elements[] = e.getStackTrace();
    for (int i = 0, n = elements.length; i < n; i++) {
        logger.log(Level.WARNING, elements[i].getMethodName());
    }
}

Creating Exception Classes

When faced with choosing the type of exception to throw, you can either use one written by someone else — the Java platform provides a lot of exception classes you can use — or you can write one of your own. You should write your own exception classes if you answer yes to any of the following questions; otherwise, you can probably use someone else's.

  • Do you need an exception type that isn't represented by those in the Java platform?
  • Would it help users if they could differentiate your exceptions from those thrown by classes written by other vendors?
  • Does your code throw more than one related exception?
  • If you use someone else's exceptions, will users have access to those exceptions? A similar question is, should your package be independent and self-contained?

An Example

Suppose you are writing a linked list class. The class supports the following methods, among others:

  • objectAt(int n) — Returns the object in the nth position in the list. Throws an exception if the argument is less than 0 or more than the number of objects currently in the list.
  • firstObject() — Returns the first object in the list. Throws an exception if the list contains no objects.
  • indexOf(Object o) — Searches the list for the specified Objectand returns its position in the list. Throws an exception if the object passed into the method is not in the list.

The linked list class can throw multiple exceptions, and it would be convenient to be able to catch all exceptions thrown by the linked list with one exception handler. Also, if you plan to distribute your linked list in a package, all related code should be packaged together. Thus, the linked list should provide its own set of exception classes.

The next figure illustrates one possible class hierarchy for the exceptions thrown by the linked list.

A possible class hierarchy for the exceptions thrown by a linked list.

 

Example exception class hierarchy.

Choosing a Superclass

Any Exceptionsubclass can be used as the parent class of LinkedListException. However, a quick perusal of those subclasses shows that they are inappropriate because they are either too specialized or completely unrelated to LinkedListException. Therefore, the parent class of LinkedListExceptionshould be Exception.

Most applets and applications you write will throw objects that are Exceptions. Errors are normally used for serious, hard errors in the system, such as those that prevent the JVM from running.


Note: For readable code, it's good practice to append the string Exceptionto the names of all classes that inherit (directly or indirectly) from the Exceptionclass.
--Oracle