ArrayIndexOutOfBoundsException occurs when an attempt is made to access an element past either end of an array. ClassCastException occurs when an attempt is made to cast an object that does not have an is-a relationship with the type specified in the cast operator. A NullPointerException occurs when a null reference is used where an object is expected. Only classes that extend Throwable (package java.lang) directly or indirectly can be used with exception handling.
Java does not allow division by zero in integer arithmetic. ◦ Throws an ArithmeticException. ◦ Can arise from a several problems, so an error message (e.g., “/ by zero”) provides more specific information. Java does allow division by zero with floating-point values. ◦ Such a calculation results in the value positive or negative infinity ◦ Floating-point value that displays as Infinity or -Infinity. ◦ If 0.0 is divided by 0.0, the result is NaN (not a number), which is represented as a floating-point value that displays as NaN.
Last line of the stack trace started the call chain. Each line contains the class name and method followed by the filename and line number. The top row of the call chain indicates the throw point—the initial point at which the exception occurred.
The application in Fig. 11.2 uses exception handling to process any ArithmeticExceptions and InputMistmatchExceptions that arise. If the user makes a mistake, the program catches and handles (i.e., deals with) the exception—in this case, allowing the user to try to enter the input.
When an exception occurs in a try block, the catch block that executes is the first one whose type matches the type of the exception that occurred. Use the System.err (standard error stream) object to output error messages. ◦ By default, displays data to the command prompt.
Uncaught exception—one for which there are no matching catch blocks. Recall that previous uncaught exceptions caused the application to terminate early. ◦ This does not always occur as a result of uncaught exceptions. Java uses a multithreaded model of program execution. ◦ Each thread is a concurrent activity. ◦ One program can have many threads. ◦ If a program has only one thread, an uncaught exception will cause the program to terminate. ◦ If a program has multiple threads, an uncaught exception will terminate only the thread in which the exception occurred.
If an exception occurs in a try block, the try block terminates immediately and program control transfers to the first matching catch block. After the exception is handled, control resumes after the last catch block. Known as the termination model of exception handling. ◦ Some languages use the resumption model of exception handling, in which, after an exception is handled, control resumes just after the throw point.
If no exceptions are thrown in a try block, the catch blocks are skipped and control continues with the first statement after the catch blocks ◦ We’ll learn about another possibility when we discuss the finally block in Section 11.6. The try block and its corresponding catch and/or finally blocks form a try statement.
When a try block terminates, local variables declared in the block go out of scope. ◦ The local variables of a try block are not accessible in the corresponding catch blocks. When a catch block terminates, local variables declared within the catch block (including the exception parameter) also go out of scope. Any remaining catch blocks in the try statement are ignored, and execution resumes at the first line of code after the try…catch sequence. ◦ A finally block, if one is present.
throws clause—specifies the exceptions a method might throw if problems occur. ◦ Must appear after the method’s parameter list and before the body. ◦ Contains a comma-separated list of the exception types. May be thrown by statements in the method’s body or by methods called from there. ◦ Clients of a method with a throws clause are thus informed that the method might throw exceptions.
Exception handling is designed to process synchronous errors, which occur when a statement executes. Common examples in this book: ◦ out-of-range array indices ◦ arithmetic overflow ◦ division by zero ◦ invalid method parameters ◦ thread interruption
Exception handling is not designed to process problems associated with asynchronous events ◦ disk I/O completions ◦ network message arrivals ◦ mouse clicks and keystrokes
Class Exception and its subclasses represent exceptional situations that can occur in a Java program ◦ These can be caught and handled by the application. Class Error and its subclasses represent abnormal situations that happen in the JVM. ◦ Errors happen infrequently. ◦ These should not be caught by applications. ◦ Applications usually cannot recover from Errors.
To satisfy the catch part of the catch-or-declare requirement, the code that generates the exception must be wrapped in a try block and must provide a catch handler for the checked-exception type (or one of its superclasses). To satisfy the declare part of the catch-or-declare requirement, the method must provide a throws clause containing the checked-exception type after its parameter list and before its method body. If the catch-or-declare requirement is not satisfied, the compiler will issue an error message.
If multiple catch blocks match a particular exception type, only the first matching catch block executes. It’s a compilation error to catch the exact same type in two different catch blocks associated with a particular try block.
Because a finally block always executes, it typically contains resource-release code. Suppose a resource is allocated in a try block. ◦ If no exception occurs, control proceeds to the finally block, which frees the resource. Control then proceeds to the first statement after the finally block. ◦ If an exception occurs, the try block terminates. The program catches and processes the exception in one of the corresponding catch blocks, then the finally block releases the resource and control proceeds to the first statement after the finally block. ◦ If the program doesn’t catch the exception, the finally block still releases the resource and an attempt is made to catch the exception in a calling method.
throw statement—indicates that an exception has occurred. ◦ Used to throw exceptions. ◦ Indicates to client code that an error has occurred. ◦ Specifies an object to be thrown. ◦ The operand of a throw can be of any class derived from class Throwable.
Sometimes a method responds to an exception by throwing a different exception type that is specific to the current application. If a catch block throws a new exception, the original exception’s information and stack trace are lost. Earlier Java versions provided no mechanism to wrap the original exception information with the new exception’s information. ◦ This made debugging such problems particularly difficult. Chained exceptions enable an exception object to maintain the complete stack-trace information from the original exception. For any chained exception, you can get the Throwable that initially caused that exception by calling Throwable method getCause.
A typical new exception class contains only four constructors: ◦ one that takes no arguments and passes a default error message String to the superclass constructor; ◦ one that receives a customized error message as a String and passes it to the superclass constructor; ◦ one that receives a customized error message as a String and a Throwable (for chaining exceptions) and passes both to the superclass constructor; ◦ and one that receives a Throwable (for chaining exceptions) and passes it to the superclass constructor.
A precondition must be true when a method is invoked. ◦ Describes constraints on method parameters and any other expectations the method has about the current state of a program just before it begins executing. ◦ If the preconditions are not met, the method’s behavior is undefined. ◦ You should never expect consistent behavior if the preconditions are not satisfied.
A postcondition is true after the method successfully returns. ◦ Describes constraints on the return value and any other side effects the method may have. ◦ When calling a method, you may assume that a method fulfills all of its postconditions. ◦ If writing your own method, document all postconditions so that others know what to expect when they call your method, and you should make certain that your method honors all its postconditions if its preconditions are met. When preconditions or postconditions are not met, methods typically throw exceptions.
As an example, examine String method charAt, which has one int parameter—an index in the String. ◦ For a precondition, method charAt assumes that index is greater than or equal to zero and less than the length of the String. ◦ If the precondition is met, the postcondition states that the method will return the character at the position in the String specified by the parameter index. ◦ Otherwise, the method throws an Index-Out-Of-Bounds-Exception. ◦ We trust that method charAt satisfies its postcondition, provided that we meet the precondition. ◦ We need not be concerned with the details of how the method actually retrieves the character at the index.
Some programmers state preconditions and postconditions informally as part of the general method specification, while others prefer a more formal approach by explicitly defining them. State the preconditions and postconditions in a comment before the method declaration. Stating the preconditions and postconditions before writing a method will also help guide you as you implement the method.
When implementing and debugging a class, it’s sometimes useful to state conditions that should be true at a particular point in a method. Assertions help ensure a program’s validity by catching potential bugs and identifying possible logic errors during development. Preconditions and postconditions are two types of assertions.
Java includes two versions of the assert statement for validating assertions programatically. assert evaluates a boolean expression and, if false, throws an AssertionError (a subclass of Error). assert expression; throws an AssertionError if expression is false. assert expression1 : expression2; evaluates expression1 and throws an AssertionError with expression2 as the error message if expression1 is false. Can be used to programmatically implement preconditions and postconditions or to verify any other intermediate states that help you ensure your code is working correctly.
You use assertions primarily for debugging and identifying logic errors in an application. You must explicitly enable assertions when executing a program ◦ They reduce performance. ◦ They are unnecessary for the program’s user. To enable assertions, use the java command’s -ea command-line option, as in java -ea AssertTest
For example, a file-processing application could process a file with a try-with-resources statement to ensure that the file is closed properly when it’s no longer needed. Each resource must be an object of a class that implements the AutoCloseable interface—and thus provides a close method.
The general form of a try-with-resources statement is try (ClassName theObject = new ClassName()) { // use theObject here } catch ( Exception e ) { // catch exceptions that occur while using the resource }
ClassName is a class that implements the AutoCloseable interface.
Java 8 introduced effectively final local variables If the compiler can infer that the variable could have been declared final, because its enclosing method never modifies the variable after it’s declared and initialized, then the variable is effectively final ◦ Frequently are used with lambdas (Chapter 17, Lambdas and Streams). As of Java SE 9, you can create an AutoCloseable object and assign it to a local variable that’s explicitly declared final or that’s effectively final Then, you can use it in a try-with-resources statement that releases the object’s resources at the end of the try block.
ClassName theObject = new ClassName(); try (theObject) { // use theObject here, then release its resources at // the end of the try block } catch (Exception e) { // catch exceptions that occur while using the resource } As before, you can separate with a semicolon (;) multiple AutoCloseable objects in the parentheses following try