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

  • at least one catch block but can have many
  • only one finally block
  • both catch blocks and one finally block

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).

Exception Hierarchy

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 {
     /* some code goes here */
}
catch (IndexOutOfBoundsException e) {
   e.getMessage();
   e.printStackTrace();
}

Note: both ArrayIndexOutOfBoundsException and StringIndexOutOfBoundsException will be caught by the catch statement.

Not advised

try {
     /* some code goes here */
}
catch (Exception e) {
   e.getMessage();
   e.printStackTrace();
}

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 {
      /* some code that opens a file */
}
catch (FileNotFoundException e) {
   System.err.println("File Not Found");
   System.err.println(e.getMessage());
   e.printStackTrace();
}
catch (IOException e) {
   System.err.println("IO Error ");
   System.err.println(e.toString());
   e.printStackTrace();
}

Note: the first catch clause will only be executed if the file cannot be found, otherwise any other IO exception will be caught by the secound catch clause. Note that the more specific exception clause is above the more general exception clause

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
   /* Some code goes here */
   throw new myException1();                               ## throw 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

/**
* @(#)exceptionTest.java
*
* exceptionTest application
*
* @author
* @version 1.00 2008/9/10
*/

public class exceptionTest {

   // When you have a checked exception you need to declare to throw it
   // when you a have a unchecked exception you don't need to declare to throw it

   public static void main(String[] args) {

      // This class extends Exception a checked exception
      myCustomException1 m1 = new myCustomException1();

      // This class extends RuntimeException a uncheck exception
      myCustomException2 m2 = new myCustomException2();

      // This class throws the exception back to a calling method
      // here i use the throws keyword in a method
      myCustomException3 m3 = new myCustomException3();

      // run the checked exception method
      m1.myMethodTest();

      // run the throwing back exception method
      m3.myMethodTest();

      // run the uncheck exception method
      m2.myMethodTest();
   }
}

// a checked exception must be caught, you have to have a try and catch block
// otherwise the compiler will complain
class myCustomException1 extends Exception {

   void myMethodTest() {
      try {
         throw new Exception();
      }
      catch (Exception e) {
         e.printStackTrace();
         System.out.println("\n\n");
      }
   }
}

// a unchecked exception which does not have to be caught - notice no try and catch blocks
class myCustomException2 extends RuntimeException {
      void myMethodTest() {
         throw new NullPointerException();
      }
}

// Here we are throwing back the exception to the calling method note the keyword
// throws on the myMethodTest2 method, also note the try/catch block in the original
// method myMethodTest which will catch the thrown exception by myMethodTest2
class myCustomException3 extends Exception {

   void myMethodTest() {
      try {
         myMethodTest2();
      }
      catch (Exception e) {
         e.printStackTrace();
         System.out.println("\n\n");
      }
   }
   
   void myMethodTest2() throws Exception {
      try {
         throw new Exception();
      }
      catch (Exception e) {
         throw e;
      }
   }
}

Assertions

When you are coding you sometimes add some debugging code to find out whats going on with your program

Not using assertions

while (true) {
   if ( x> 2) {
      break;
   }
   System.out.println("Not expecting this, something has gone wrong. X =" + x);
}

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
private void doStuff() {
   assert (y > x);
   // more code assuming y is greater than x
}

## Simple
private void doStuff() {
   assert (y > x): "y is" + y " " x is " + x;
   // more code assuming y is greater than x
}

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