Java Exceptions and Assertions
The term exception means "exceptional condition" and is an occurence that alters the normal program flow. A bunch of things can lead to exceptions, including hardware failures, resource exhaustion and good old bugs. When an exceptional event occurs in Java, an exception is said to be thrown. The code that handles the exception is called the exception handler and it catches the thrown exception. Exception handling works by transferring the execution of a program to an appropriate exeception handler which knows how to deal with the exception.
Exception handling should be used
This page is a quick guide to using exceptions and assertions and for a full explaination you should consult the Java Documentation
Keywords
There are three keywords that handle a basic exception
Exception Keywords |
|
try | is used to define a block of code in which the exception may occur. This block of code is called a guarded region (which means risky code goes here). A try block has to have either one of the following
The order must be catch block/s then finally block |
catch | catch clauses match a specific exception (or class of exceptions) to a block of code that handles it. |
finally (optional) | A finally block encloses code that will always be executed whether the an exception was thrown or not. This block of code can be useful if you want to tidy up after you have tried your risky code for an example you can closed down any network sockets, database links, etc. You can have only one finally block for a try statement and it must be after the catch blocks if there are any. |
Exception Example |
|
defination | try { // your risky code goes here , could be one line or many lines of code // remember this is know as the guarded region } catch (FirstException) { // your code handles the specific exception here } catch (SecondException) { // your code handles the specific exception here } finally { // This code will always always execute even if an exception was not thrown, unless // the JVM aborts or System.exit() method is called } |
Propagating Uncaught Exceptions
First I must explain what a call stack is, simply put the call stack is the chain of methods that your program executes to get to the current method. If you program calls main() and main() call method a(), which calls method b(), which calls method c() the call stack would look like the following
c | |
b | |
a | |
main |
The last method is at the top of the stack and the first method is at the bottom, this is know as a stack trace.
So when a exception is thrown in the top part of the stack and there is no catch statement, it passes it down to the next method again if there is no catch statement to catch the thrown exception it is passed down again. If the thrown exception goes all the way to main and still there is no catch statement to catch the thrown exception then this throws it out halting the JVM (KABOOM).
All exception classes are subtypes of class Exception, this class derives from the class throwable. The figure below shows the exception hierarchy for the eception class.
As seen above there are two subclasses that derive from Throwable, Exception and Error.
Error | represents unusual situations that are not caused by program errors or anything that would normally happen during program execution, such as JVM running out of memory, Generally your program won't be able to recover from an Eroor, so you're not required to handle them. The compiler will not complain if you do not catch these types of errors. Technically Errors are not exceptions as they do not derive from the Exception class. |
Exception | represents something that happens not as a result of a programming error, but rather because some resource is not available or some other condition required for correct execution is not present. For example if you application is supposed to communicate with another application or computer that is not answering, this is an exception that is not caused by a bug. |
Java provide many exception classes, most of which have very descriptive names, to get information about a exception class you use the exception object itself as all exception objects are derived from the Throwable object the method printStackTrace() is inherited which provides useful information about the object. The printStackTrace() method prints the name of each method of the calling stack from the top, also a another helpful for debugging is the getMessage() method which returns the detail message string of this throwable.
Some exception classes can catch multiple conditions for an example the class IndexOutOfBoundsException has two subclasses, ArrayIndexOutOfBoundsException and StringIndexOutOfBoundsException. You may want to write one exception handler that deals with exceptions produced by either type of boundary error but you might not be concerned with which exception you actually have, of cause you can abuse this by using the Exception class to catch eveything which is considered bad programming.
catch more than one type of exception | try { Note: both ArrayIndexOutOfBoundsException and StringIndexOutOfBoundsException will be caught by the catch statement. |
Not advised | try { Note: this defeats the design objective as this could handle everything thrown at it |
Exception Matching
If you have an exception hierarchy composed of a superclass exception and a number of subtypes and you're interested in handling one of the subtypes in a special way but want to handle all the rest together you need only write two catch clauses. Handlers for the most specific exceptions must always be palced above those for more general exceptions otherwise the compiler will complain.
Exception Matching |
try { |
Exception Declaration
Exceptions that a method might or might not throw have to be declared, its basically letting the world know about it. The throws keyword is used to declare an exception
Keywords |
|
throws | used in a method definition to declare the exceptions to be thrown by the emthod |
throw | used to throw an exception which hopefully will be caught |
Examples |
|
throws/throw | void myFunction() throws myException1, myException2 { ## throws statement Note: the stack above will handle the thrown exception |
There are two flavours of exception, the bottomline is if a client can reasonably be expected to recover from an exception make a checked exception, if the client cannot do anything to recover from the exception make it a unchecked exception.
checked | include all subtypes of Exception (excluding classes that extend RuntimeException). Checked exceptions are subject to the handle and declare rule, any method that might throw a checked exception (including methods that invoke methods that can throw a checked exception) must either declare the exception using the throws keyword or handle the exception with an appropriate try/catch. |
unchecked | Runtime exceptions are referred as unchecked exceptions, thus you do not need to declare them. |
Checked/Unchecked Example |
|
check/unchecked | /** public class exceptionTest { // This class throws the exception back to a calling method // run the throwing back exception method // a checked exception must be caught, you have to have a try and catch block // a unchecked exception which does not have to be caught - notice no try and catch blocks // Here we are throwing back the exception to the calling method note the keyword |
When you are coding you sometimes add some debugging code to find out whats going on with your program
Not using assertions | while (true) { |
The above is normal coding when you are trying to find out what values are set to when you program breaks down, once you are done fixing the program you want to remove any debugging code which can be a problem. This is were assertions come in, Assertions let you test your assumptions during development, but the assertion code in-effect evaporates when the program is deployed in production. If the Assertion is not true then a stop-the-world AssertError is thrown (do not ever handle these).
Using Assertions | ## really simple ## Simple Note: if the assert is not true then a AssertionError is thrown never try to handle these |
Assertion have the following rules
There are a number of options that you need to use in order to get assertions working
Compiling | When compiling make sure to add the option (-source 1.5) > javac -source 1.5 <class> |
Enabling | When running the application add the option (-ea or enableassertions) > java -ea <class> > java -enableassertions <class> |
Disabling | When running the application add the option (-da or disableassertions) > java -da <class> > java -disableassertions <class> |
Enabling/Disabling | java -ea -da:uk.co.datadisk.graphics Note: we enable all assertions but disable assertions for the graphics class, by default assertions are disabled. |
Here is a list when you should or should not use assertions