Exception Handling in Java
What is an Exception?
An exception is an object that represents an error or an
exceptional situation that has occurred
- Could represent the run-time environment detecting an operation that's
impossible to carry out
- Could be created by a method in response to a special situation
- In Java, exception objects are all children of class
Throwable. This base class has two main child classes:
- class Exception: base class for most exception types
- class Error: class that represents things that are usually
not recoverable (e.g. VirtualMachineError)
- Examples of a few common exception types:
- IndexOutOfBoundsException: for when an array index is out of
bounds
- FileNotFoundException: when attempting to open a file that
does not exist
- Java has many built-in exception classes in its libraries
- Users can create new exception types -- just derive from class
Exception or one of its subclasses
- Exceptions are used to build robust programs. Exceptions allow the
programmer to recover from an error or exceptional event. Java was
originally a language for embedded systems (TVs, phones, watches,
etc.) These systems should never stop working, exceptions are
needed for these systems.
Exception categories in Java
Java has two primary kinds of exceptions
- Checked Excepctions (Normal exceptions)
- These are exceptions that could occur in any program, regardless of
how well it is coded
- These are typically thrown manually by a method
- If a checked exception is "thrown" in a method, then the method must
catch it, or must "claim" it (i.e. declare that it can be
thrown).
- Example: FileNotFoundException. No matter how well a
program is coded, a user might pick a non-existent file to open
- Unchecked Exceptions (Runtime exceptions)
- These have the potential to be in any code, arising automatically due
to runtime issues
- The class RuntimeException and all of its subclasses are in
this category
- Compiler does not require these to be "caught" or "claimed".
- Usually, a runtime exception can be eliminated by coding better
- Example: IndexOutOfBoundsException. This occurs when user
of an array uses a bad index. Fix the code so this won't
happen!
When to use Exceptions
- Exception handlers shouldn't be used for all traditional
error-checking situations. Sometimes conventional error-checking is
more appropriate.
- Exceptions are best used when:
- its a problem that occurs less frequently
- the error doesn't need to be (or can't be) handled in the
block in which it occurs
- an error would otherwise result in program termination
- A common exception handling situation:
- Every method has a specific job to do. Suppose a method is supposed
to return an answer as the return value.
- If a situation could occur so that the method could not arrive at an
answer, what should it return? (i.e. there is no valid
answer!)
- By throwing an exception, the method can bypass the need for any
return -- sending out an error message (via an exception object)
instead)
- The calling module (whoever called the function) would have to
"catch" the exception, to discover what occurred
How do you do exception handling?
The process involves:
- Claiming exceptions - each method needs to specify what exceptions
it expects might occur (i.e. what it will throw, and not handle
internally)
- Throwing an exception - When an error situation occurs that fits an
exception situation, an exception object is created and thrown
- Catching an exception - Exception handlers (blocks of code) are
created to handle the different expected exception types. The appropriate
handler catches the thrown exception and performs the code in the
block
Claiming Exceptions
In a Java method claim an exception with the keyword throws.
This goes at the end of the method's prototype and before the
definition. Multiple exceptions can be claimed, with a comma-separated
list. Examples:
public void myMethod() throws IOException
public void yourMethod() throws IOException, AWTException, BobException
Throwing Exceptions
In Java, use the keyword throw, along with the type of exception
being thrown. An exception is an object, so it must be created with the
new operator. It can be created within the throw
statement or before it. Examples:
throw new BadHairDayException();
MyException m = new MyException();
throw m;
if (personOnPhone != bubba)
throw new Exception("Stranger on the phone!!");
Note that this is different than the keyword throws, which is
used in claiming exceptions.
Catching Exceptions
Keywords: try, catch, finally
- Any group of statements that might throw an exception (or where you
want to watch for Runtime or Error exceptions) -- place inside a
try block.
- If an exception occurs (i.e. "is thrown"), execution ends at the
"throw point" and will only resume if the exception is "caught"
- After the try block, there should be one or more
catch blocks
- Each catch block has a parameter -- the type of exception
that this block will handle
- There can be multiple catch blocks
- If an exception is thrown, the first matching catch
block is the one that runs
- An optional finally block can be used
- A finally block is always executed, no matter how
control leaves the try block
Trivial Example
- Look at this example.
What happens if we enter 0 for y?
- Now try this revised version
of the example. When run, it does not crash when the exception is
thrown. Instead, the exception is handled.
- Is this really a place where we need exception handling
techniques, though?
Example Layout -- try, catch, finally
try
{
// lots of IO code opening and reading from/to files
}
catch (FileNotFoundException)
{
// tell the user and probably repeat try block
}
catch (EOFException)
{
// hit the End Of File marker early
}
catch (IOException)
{
// blanket catch for all other IO problems
}
finally
{
// make sure to close any files that might be open
}
What happens if an exception is not caught?
- If an exception is not caught (with a catch block), the
runtime system will abort the program (i.e. crash) and an exception
message will print to the console. The message typically includes:
- name of exception type
- short description
- stack trace
- For a checked exception, a method must either catch an
exception (handle internally) or claim it (declare that it will be thrown)
- This is enforced by compiler.
- Claiming an exception is giving information to the caller, so that
they will know to catch it!
- For an unchecked exception (runtime exception), there's no
compiler enforcement.
- Runtime exceptions could occur anywhere, arising automatically.
- Usually can be fixed by better coding
- Examples: Division by zero, array index out of bounds, null pointer
exception
Instance methods in exception objects
Exception objects are created from classes, which can have instance
methods. There are some special instance methods that all
exception objects have (inherited from Throwable):
- public String getMessage() -- returns a detailed message
about the exception
- public String toString() -- returns a short message
describing the exception
- public String getLocalizedMessage()
- public void printStackTrace()
Exception Handling in C++
While the concepts are largely the same, the syntax differs a little
- In C++, there's no finally block
- In C++, throw is used for both "claiming" and throwing
exceptions
- C++ uses keywords try, catch, throw
- Class exception comes from the library
<exception> and is part of namespace std
#include <exception>
using std::exception;
- There are some other libraries for dealing with other kinds of
exceptions. For example, runtime errors:
#include <stdexcept>
using std::runtime_error;
- In C++, the "claiming" of an exception (specifying a throw
list) on the function prototype looks like this:
void someFunction() throw (DivideByZero, SomeOtherException);
- A few code examples from Deitel C++: