Next page | Contents page |

Throwing exceptions

To "throw an exception" is to indicate that something unusual occurred. To "catch" it is to handle it. An exception is an object of a subclass of java.lang.Throwable.

Eg, in our original Squarer program, deal with the case where the user forgets to input a number on the command line:

	public static void main (String args [])
	{
	    if (args.length < 1)
	        throw new InvalidSyntaxException ("Syntax: Squarer n");
	    // else continue processing...
	}

There are 2 immediate subclasses of Throwable: subclass Error means fatal - cannot continue - but subclass Exception can and should be handled - the program may well be able to recover and continue.

Declaring thrown exceptions

If your code calls any method which can throw an exception, or directly throws an exception itself, you must either include code to handle it (next section) or declare that the current method will also throw the exception:

	public void process () throws InvalidSyntaxException
	{
	  // ...
	  someMethodWhichMayThrowInvalidSyntaxException ();
	  // ...
	}

A method may throw several types of exceptions: use a comma-separated list after the keyword throws.

Handling exceptions - try blocks

	try
	{
	  // Execute some code which may throw an exception
	}
	catch (SomeException e) // optional: 0 or more catches
	{
	  // Report this type of exception or handle it
	}
	catch (AnotherException e) // repeat as necessary
	{
	  // Report this type of exception or handle it
	}
	finally // optional
	{
	  // Code to run regardless of how the try section ended up
	}

Execution proceeds through the statements in the try block. If some exceptional condition is detected an Exception is thrown. At that point execution stops while the JVM finds a catch block that matches the type of Exception. That may be a catch block in the current method or it may be one back up in the chain of callers of this method. Execution will resume in that catch block.

The optional finally section will be executed whatever happens, before leaving the current method. Even if the try block reaches a return statement without any exceptions occurring, the finally block will be executed before the return happens. The idea is that any resources that have been opened and need to be closed can be closed here. We will see particular examples of that kind of thing soon: files opened for reading or writing.

Exception classes in java.lang

Object
   |
Throwable 
   |
Exception
   |
   |_____ClassNotFoundException
   |_____ClassNotSupportedException
   |_____IllegalAccessException
   |_____InstantiationException
   |_____InterruptedException
   |_____NoSuchFieldException
   |_____NoSuchMethodException
   |
   |_____RuntimeException
		|
		|_______ArithmeticExeption
		|_______ArrayStoreException
		|_______ClassCastException
		|_______IllegalArgumentException
		|            |___IllegalThreadStateException
		|            |___NumberFormatException
		|_______IllegalStateException
		|_______IndexOutOfBoundsException
		|            |___ArrayIndexOutOfBoundsException
		|            |___StringIndexOutOfBoundsException
		|_______NegativeArraySizeException
		|_______NullPointerException
		|_______SecurityException
		|_______UnsupportedOperationException

RuntimeException and its subclasses are special. They are called "unchecked" exceptions because the compiler does not enforce the rule about having to explictly either catch these or throw them onwards. We have already seen some of these exceptions, in Exercise 2, when Squarer was deliberately made to fail. You should have seen messages output which included the names of some subclasses of RuntimeException.

RuntimeException is spectacularly badly named. All exceptions happen at "runtime". It should really have been called UncheckedException, because that is its important feature, but we are stuck with the inappropriate name. We just have to get used to it.

NullPointerException is one that you will see often if you fail to check that a class-type variable is null before trying to use a field or method of an object you thought it referred to. It is particularly important to ensure during testing that NullPointerExceptions cannot be thrown by your code. The occurence of any subclass of RuntimeException is widely considered to be the programmer's fault - he should have prevented it.

Many packages define further subclasses of java.lang.Exception.

Writing your own exception classes

This is a quite reasonable thing to do. It is quite easy: just extend either Exception (to make a checked exception - the compiler enforces handling or throwing) or RuntimeException (for an unchecked one) and override one or more constructors:

public class OhNoException extends Exception
{
	public OhNoException (String msg)
	{
		super (msg); 
	}
}

Examples of use:

	if (some condition)
	throw new OhNoException ("Failed because ... ");

	public void someMethod () throws OhNoException 
	{
		//... 
	}

	try 
	{
		someMethod (); 
	}
	catch (OhNoException ex)
	{
	  java.util.logging.Logger.getLogger ("app").log (Level.SEVERE, "someMethod", ex);
	}

Some tips about exceptions

Next page | Contents page |