Previous Table of Contents Next


14.2.13.4. catch

A try block may be followed by zero or more catch clauses that specify code to handle various types of exceptions. catch clauses have an unusual syntax: Each is declared with an argument, much like a method argument. This argument must be of type Throwable or a subclass. When an exception occurs, the first catch clause that has an argument of the appropriate type is invoked. The type of the argument must match the type of the exception object, or it must be a superclass of the exception. This catch argument is valid only within the catch block, and refers to the actual exception object that was thrown.

The code within a catch block should take whatever action is necessary to cope with the exceptional condition. If the exception was a java.io.FileNotFound\%Exception exception, for example, you might handle it by asking the user to check his or her spelling and try again. Note that it is not required to have a catch clause for every possible exception—in some cases the correct response is to allow the exception to propagate up and be caught by the invoking method. In other cases, such as a programming error signaled by NullPointerException, the correct response is to not catch the exception at all, but to allow it to propagate and to have the Java interpreter exit with a stack trace and an error message.

14.2.13.5. finally

The finally clause is generally used to clean up (close files, release resources, etc.) after the try clause. What is useful about the finally clause is that the code in a finally block is guaranteed to be executed, if any portion of the try block is executed, regardless of how the code in the try block completes. In the normal case, control reaches the end of the try block and then proceeds to the finally block, which performs any necessary cleanup.

If control leaves the try block because of a return, continue, or break statement, the contents of the finally block are executed before control transfers to its new destination.

If an exception occurs in the try block and there is a local catch block to handle the exception, control transfers first to the catch block, and then to the finally block. If there is not a local catch block to handle the exception, control transfers first to the finally block, and then propagates up to the nearest catch clause that can handle the exception.

Note that if a finally block itself transfers control with a return, continue, or break statement, or by raising an exception, the pending control transfer is abandoned, and this new transfer is processed.

Also note that try and finally can be used together without exceptions or any catch clauses. In this case, the finally block is simply cleanup code that is guaranteed to be executed regardless of any break, continue, or return statements within the try clause.

14.2.13.6. Declaring Exceptions

Java requires that any method that can cause a “normal exception” to occur must either catch the exception or specify the type of the exception with a throws clause in the method declaration.11 Such a throws clause might look like these:


11C++ programmers note that Java uses throws where C++ uses throw.
   public void open_file() throws IOException {
       // Statements here that might generate
       // an uncaught java.io.IOException
   }
   public void myfunc(int arg) throws MyException1, MyException2    {
       ...
   }

Note that the exception class specified in a throws clause may be a superclass of the exception type that is actually thrown. Thus if a method throws exceptions a, b, and c, all of which are subclasses of d, the throws clause may specify all of a, b, and c, or it may simply specify d.

We said above that the throws clause must be used to declare any “normal exceptions.” This oxymoronic phrase refers to any subclass of Throwable that is not a subclass of Error or a subclass of RuntimeException. Java does not require these types of exceptions to be declared because practically any method can conceivably generate them, and it would quickly become tedious to properly declare them all. For example, every method running on a buggy Java interpreter can throw an InternalError exception (a subclass of Error) and it doesn’t make sense to have to declare this in a throws clause for every method. Similarly, as far as the Java compiler is concerned, any method that accesses an array can generate an ArrayIndexOutOfBoundsException exception (a subclass of RuntimeException).

The standard exceptions that you often have to declare are java.io.IOException and a number of its more specific subclasses. java.lang.InterruptedException and several other less commonly used exceptions must also be declared. How do you know when you have to declare a throws clause? One way is to pay close attention to the documentation for the methods you call—if any “normal exceptions” can be thrown, either catch them or declare them. Another way to know what exceptions you’ve got to declare is to declare none and wait for the compilation errors—the compiler will tell you what to put in your throws clause!


Previous Table of Contents Next