Java 7 Exception Handling
An exception is an anomalous
condition that alters or interrupts the flow of execution. Java provides
built-in exception handling to deal with such conditions. Exception handling
should not be part of normal program flow.
The
Exception Hierarchy
As
shown in Figure 7-1,
all exceptions and errors inherit from the class Throwable, which inherits from
the class Object.
Figure 7-1. Snapshot of the exception hierarchy
Checked/Unchecked
Exceptions and Errors
Exceptions
and errors fall into three categories: checked exceptions, unchecked
exceptions, and errors.
Checked Exceptions
•
Checked exceptions are checked by the compiler at compile time.
•
Methods that throw a checked exception must indicate so in the method
declaration using the throws clause. This
must
continue all the way up the calling stack until the exception is handled.
•
All checked exceptions must be explicitly caught with a catch block.
•
Checked exceptions include exceptions of the type Excep tion, and all classes that are subtypes of Exception, except for RuntimeException and the subtypes of Runtime Exception.
The
following is an example of a method that throws a checked exception:
//
Method declaration that throws
// an
IOException
void readFile(String
filename)
throws IOException
{
...
}
Unchecked Exceptions
• The compiler does not check unchecked exceptions
at compile time.
•
Unchecked exceptions occur during runtime due to programmer error
(out-of-bounds index, divide by zero, and null pointer exception) or system
resource exhaustion.
• Unchecked
exceptions do not have to be caught.
• Methods that
may throw an unchecked exception do not have to (but can) indicate this in the
method declaration.
• Unchecked
exceptions include exceptions of the type RuntimeException and all subtypes of RuntimeException.
Errors
• Errors are
typically unrecoverable and present serious conditions.
• Errors are
not checked at compile time and do not have to be (but can be) caught/handled.
T IP
***Any checked
exceptions, unchecked exceptions, or errors can be caught.
Common
Checked/Unchecked Exceptions and Errors
There are
various checked exceptions, unchecked exceptions, and unchecked errors that are
part of the standard Java platform. Some are more likely to occur than others.
Common
Checked Exceptions :
ClassNotFoundException
Thrown when a
class cannot be loaded because its definition cannot be found.
IOException
Thrown when a
failed or interrupted operation occurs. Two common subtypes of IOException are
EOFException and
FileNotFoundException.
FileNotFoundException
Thrown when an
attempt is made to open a file that cannot be found.
SQLException
Thrown when
there is a database error.
InterruptedException
Thrown when a
thread is interrupted.
NoSuchMethodException
Thrown when a
called method cannot be found.
CloneNotSupportedException
Thrown when clone() is called by an
object that is not cloneable.
Common Unchecked Exceptions :
ArithmeticException
Thrown to indicate
that an exceptional arithmetic condition has occurred.
ArrayIndexOutOfBoundsException
Thrown to
indicate index out of range.
ClassCastException
Thrown to
indicate an attempt to cast an object to a subclass of which it is not an
instance.
IllegalArgumentException
Thrown to
indicate that an invalid argument has been passed to a method.
IllegalStateException
Thrown to
indicate that a method has been called at an inappropriate time.
IndexOutOfBoundsException
Thrown to
indicate that an index is out of range.
NullPointerException
Thrown when
code references a null object but a nonnull object is required.
NumberFormatException
Thrown to
indicate an invalid attempt to convert a string to a numeric type.
Common Errors :
AssertionError
Thrown to
indicate that an assertion failed.
ExceptionInInitializeError
Thrown to
indicate an unexpected exception in a static initializer.
VirtualMachineError
Thrown to
indicate a problem with the JVM.
OutOfMemoryError
Thrown when
there is no more memory available to allocate an object or perform garbage
collection.
NoClassDefFoundError
Thrown when the
JVM cannot find a class definition that was found at compile time.
StackOverflowError
Thrown to
indicate that a stack overflow occurs.
Exception Handling Keywords :
In Java,
error-handling code is cleanly separated from errorgenerating code. Code that
generates the exception is said to “throw” an exception, whereas code that
handles the exception is said to “catch” the exception:
// Declare an exception
public void methodA() throws IOException {
...
throw new IOException();
...
}
// Catch an exception
public void methodB() {
...
/* Call to methodA must be in a try/catch
block
** since the exception is a checked exception;
** otherwise methodB could throw the exception
*/
try {
methodA();
}catch (IOException ioe) {
System.err.println(ioe.getMessage());
ioe.printStackTrace();
}
}
The throw Keyword
To
throw an exception, use the keyword throw. Any checked/unchecked
exception and error can be thrown:
if (n == -1)
throw new EOFException();
The try/catch/finally
Keywords
Thrown
exceptions are handled by a Java try, catch, finally block. The Java
interpreter looks for code to handle the exception, first looking in the
enclosed block of code, and then propagating up the call stack to main() if necessary. If the exception is not handled, the program exits
and a stack trace is printed:
try {
method();
} catch (EOFException eofe) {
eofe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
// cleanup
}
The try-catch Statement
The try-catch statement
includes one try and
one or more catch blocks.
The try block
contains code that may throw exceptions. All checked exceptions that may be
thrown must have a catch block
to handle the exception. If no exceptions are thrown, the try block
terminates normally. A try
block may have zero or more catch clauses to handle the exceptions.
T IP
*** A try block must have
at least one catch or finally block associated with it.
There
cannot be any code between the try block and any of the catch blocks (if
present) or the finally block (if present). The catch block(s) contain code to
handle thrown exceptions, including printing information about the exception to
a file, giving users an opportunity to input correct information. Note that catch
blocks should never be empty because such “silencing” results in exceptions
being hidden, making errors harder to debug. A common convention for naming the
parameter in the catch clause is a set of letters representing each of the
words in the name of the exception:
catch (ArrayIndexOutOfBoundsException aioobe) {
aioobe.printStackStrace();
}
Within a catch clause,
a new exception may also be thrown if necessary. The order of the catch clauses
in a try/catch block defines the precedence for catching exceptions. Always
begin with the most specific exception that may be thrown and end with the most
general.
T IP
*** Exceptions
thrown in the try block are directed to the first catch clause containing
arguments of the same type as the exception object or superclass of that type.
The catch block with the Exception parameter should always be last in the ordered
list.
If
none of the parameters for the catch clauses match the exception thrown, the
system will search for the parameter that matches the superclass of the
exception.
The try-finally Statement
The
try-finally statement includes one try and one finally block. The finally block
is used for releasing resources when necessary:
public void testMethod() throws IOException {
FileWriter
fileWriter = new FileWriter("\\data.txt");
try {
fileWriter.write("Information...");
} finally {
fileWriter.close();
}
}
This
block is optional and is only used where needed. When used, it is executed last
in a try-finally block and will always be executed, whether or not the try block
terminates normally. If the finally block throws an exception, it must be
handled.
The try-catch-finally Statement
The
try-catch-finally statement includes one try, one or more catch blocks, and one
finally block. For this statement, the finally block is also used for cleanup
and releasing resources:
public void testMethod() {
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter("\\data.txt");
fileWriter.write("Information...");
} catch (IOException ex)
{
ex.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
This
block is optional and is only used where needed. When used, it is executed last
in a try-catch-finally block and will always be executed, whether or not the try
block terminates normally or the catch clause(s) were executed. If the finally block
throws an exception, it must be handled.
The try-with-resources Statement
The
try-with-resources statement is used for declaring resources that must be
closed when they are no longer needed. These resources are declared in the try block:
public void testMethod() throws IOException {
try (FileWriter fw = new FileWriter("\\data.txt"))
{
fw.write("Information...");
}
}
Any
resource that implements the Autoclosable interface may be used
with the try-with-resources statement.
The multi-catch Clause
The
multi-catch clause is used to allow for multiple exception arguments in one catch clause:
boolean isTest = false;
public void testMethod() {
try {
if (isTest) {
throw new IOException();
} else {
throw new SQLException();
}
} catch (IOException | SQLException e) {
e.printStackTrace();
}
}
The Exception Handling
Process
Here
are the steps to the exception handling process:
1.
An exception is encountered resulting in an exception object being created.
2.
A new exception object is thrown.
3.
The runtime system looks for code to handle the exception beginning with the
method in which the exception object was created. If no handler is found, the
runtime environment traverses the call stack (the ordered list of methods) in
reverse looking for an exception handler. If the exception is
not handled, the program exits and a stack trace is automatically output.
4. The runtime
system hands the exception object off to an exception handler to handle (catch)
the exception.
Defining Your Own
Exception Class
Programmer-defined
exceptions should be created when those other than the existing Java exceptions
are necessary. In general, the Java exceptions should be reused wherever
possible:
•
To define a checked exception, the new exception class must extend the Exception class, directly or indirectly.
•
To define an unchecked exception, the new exception class must extend the RuntimeException class, directly or indirectly.
•
To define an unchecked error, the new error class must extend the Error class. User-defined exceptions should have at least two
constructors—a constructor that does not accept any arguments and a constructor
that
does:
public class ReportException extends Exception {
public ReportException () {}
public ReportException (String message, int reportId) {
...
}
}
Printing Information About
Exceptions
The
methods in the Throwable
class that provide information about thrown
exceptions are getMessage(), toString, and print StackTrace(). In general, one of
these methods should be called in the catch clause handling the
exception. Programmers can also write code to obtain additional useful
information when an exception occurs (i.e., the name of the file that was not
found).
The getMessage() Method
The
getMessage() method returns a detailed message string about the exception:
try {
new FileReader("file.js");
} catch (FileNotFoundException fnfe) {
System.err.println(fnfe.getMessage());
}
The toString() Method
This
toString() method returns a detailed message string about the exception,
including its class name:
try {
new FileReader("file.js");
} catch (FileNotFoundException fnfe) {
System.err.println(fnfe.toString());
}
The printStackTrace() Method
This
printStackTrace() method returns a detailed message string about the exception,
including its class name and a stack trace from where the error was caught, all
the way back to where it was thrown:
try {
new FileReader("file.js");
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
The
following is an example of a stack trace. The first line contains the contents
returned when the toString() method is invoked on an exception object. The
remainder shows the method calls beginning with the location where the
exception was thrown all the way back to where it was caught and handled:
java.io.FileNotFoundException: file.js (The system
cannot
find the file specified)
at
java.io.FileInputStream.open(Native Method)
at
java.io.FileInputStream.(init)
(FileInputSteam.java:106)
at
java.io.FileInputStream.(init)
(FileInputSteam.java:66)
at
java.io.FileReader(init)(FileReader.java:41)
at
EHExample.openFile(EHExample.java:24)
at
EHExample.main(EHExample.java:15)
Comments
Post a Comment