Exceptions
Home - About Us
 

When something goes horribly wrong in your Java application, one way to handle that situation is to "throw an exception". An Exception-based object is created, the object is filled with information about the error that just occurred, and then the Exception object is thrown. Another part of the Java program is setup to receive, or catch, the thrown exception. The receiving code takes any required actions in response to the error, then processing continues normally from the place in the program where the exception was caught.

There are many pre-written Java exception classes. You can use these, or create your own exception classes.

Throwing an exception

The following application uses a method named "upperCase" that only changes the first few characters of the word to uppercase (the second parameter indicates how many characters should be changed to uppercase).

public class DemoExc1
{
	public static void main(String [] args)
	{
		// Change 1st three letters to uppercase

		String s = upperCase("word", 3);
		System.out.println(s);

		// Change 1st two letters to uppercase

		String s2 = upperCase("demonstrate", 2);
		System.out.println(s2);

		System.out.println( upperCase("utility", 5) );
	}

	/**
		The upperCase method takes a String "in" and an integer 
		"number".  The method returns the String with the first 
		"number" of characters turned to upper case.
	*/

	public static String upperCase(String in, int number)
	{
		String out = in.substring(0, number).toUpperCase() + 
				in.substring(number, in.length());
		return out;
	}
}

The above application generates the following output:
WORd
DEmonstrate
UTILIty
One problem with the above upperCase method is that the caller might ask the method to change more letters than exist in the word, such as with:
String s3 = upperCase("it", 9);
One way for upperCasetto handle such an error is somehow return an error code if the conversion did not work. To follow such a solution, you first have to decide on the mechanism for returning the error code, and then after you've called the method you need to check if there was an error or not. One possible mechanism is to return a null reference if there is an error and return a valid reference to an "uppercased" String if there was no error:
public class DemoExc2
{
	public static void main(String [] args)
	{
		String s = upperCase("word", 3);

		if (s == null)
			System.err.println("Error -- index too big");
		else
			System.out.println(s);
	}

	public static String upperCase(String in, int number)
	{
		if (number > in.length())
			return null;
		else
		{
			String out = in.substring(0, number).toUpperCase() + 
				in.substring(number, in.length());
			return out;
		}
	}
}
The problem with such a method is that if you try to convert several words, and you check for an error after each conversion, then the error checking code overwhelms (in size) the amount of useful productive code. For example, if want you want to do is this:
System.out.println( upperCase("The", 1) );
System.out.println( upperCase("orange", 4) );
System.out.println( upperCase("cat", 2) );
System.out.println( upperCase("was", 2) );
System.out.println( upperCase("climbing.", 3) );
you would have to write the following to handle all of the error checking:
String s;

s = upperCase("The", 1);
if (s == null)
	System.out.println("Error -- index to big");
else 
	System.out.println( s );

s = upperCase("orange", 4);
if (s == null)
	System.out.println("Error -- index to big");
else
	System.out.println( s );

s = upperCase("cat", 2);
if (s == null)
	System.out.println("Error -- index to big");
else
	System.out.println( s );

s = upperCase("was", 2) );
if (s == null)
	System.out.println("Error -- index to big");
else
	System.out.println( s );

s = upperCase("climbing.", 3);
if (s == null)
	System.out.println("Error -- index to big");
else
	System.out.println( s );
On first glance it is difficult to determine what the above code is trying to do (uppercase the leading letters of each word in the sentence "The orange cat was climbing."). Throwing an exception can greatly aid the readability of code that needs to have error processing.

Instead of returning a null value if an error is encountered, upperCase now throws an exception:

	public static String upperCase(String in, int number)
	{
		if (number > in.length())
			throw new IndexOutOfBoundsException("The value " +
				number + " is too large for " + in);

		String out = in.substring(0, number).toUpperCase() + 
				in.substring(number, in.length());
		return out;
	}
Below, an application is run with this version of upperCase. Note that the second call to upperCase sends too large of an index.
public class DemoExc3
{
	public static void main(String [] args)
	{
		System.out.println( upperCase("word", 3) );
		System.out.println( upperCase("demonstrate", 100) );
		System.out.println( upperCase("utility", 5) );
	}

	public static String upperCase(String in, int number)
	{
		if (number > in.length())
			throw new IndexOutOfBoundsException("The value " +
				number + " is too large for " + in);

		String out = in.substring(0, number).toUpperCase() + 
				in.substring(number, in.length());
		return out;
	}
}
The output of this code is:
WOrd
Exception in thread "main" 
  java.lang.IndexOutOfBoundsException: The value 100 is too large for demonstrate
	at DemoExc3.upperCase(DemoExc3.java:17)
	at DemoExc3.main(DemoExc3.java:8)
The first word was processed correctly an it output was printed to the console. The second word generated an exception. Notice that the third word was not processed!

If an exception is thrown in a method and it is not caught in that method (such as in upperCase) then the exception exits out of that method to the calling method (in this case main). Since main does not catch the exception, it exits main (which ends the application and the exception is reported to the console).

Catching a thrown exception

In the example below, the exception is thrown by the second call to upperCase.

public class DemoExc4
{
	public static void main(String [] args)
	{
		try
		{
			System.out.println( upperCase("The", 2) );
			System.out.println( upperCase("orange", 25) );
			System.out.println( upperCase("cat", 1) );
			System.out.println( upperCase("was", 3) );
			System.out.println( upperCase("climbing.", 4) );
		}
		catch (IndexOutOfBoundsException ioe)
		{
			System.err.println("*****");
			System.err.println("Oops: " + ioe.toString());
			System.err.println("*****");
		}

		System.out.println("Finishing up the application.");
		System.out.println("Attempted to convert five words.");
	}

	public static String upperCase(String in, int number)
	{
		if (number > in.length())
			throw new IndexOutOfBoundsException("The value " +
				number + " is too large for " + in);

		String out = in.substring(0, number).toUpperCase() + 
				in.substring(number, in.length());
		return out;
	}
}

The following output was generated:
THe
*****
Oops: java.lang.IndexOutOfBoundsException: The value 25 is too large for orange
*****
Finishing up the application.
Attempted to convert five words.
All normal instructions are skipped until the exception is caught. Normal processing begins at the first instruction after the point at which the exception was caught (NOT back where the exception was thrown).

Checked versus unchecked exceptions

All Java exceptions are placed into one of two categories -- each exception is either checked or unchecked.

A programmer can write code to catch a unchecked exception, or, optionally, the programmer can decide to completely ignore the exception. The drawback to not catching an exception is that a completely uncaught exception will crash your program, which is not a very elegant way to respond to an error.

On the other hand, checked exceptions must be addressed in some way by the programmer. A checked exception must either be successfully caught in a catch block, or, if a method chooses not to catch a checked exception then the method must use the throws keyword to announce that it might be emit an uncaught exception.

Which exceptions are checked, and which are unchecked? The RuntimeException is an unchecked exception, as are all descendants of the RuntimeException class. All other exceptions are checked:

Exception tree showing unchecked and checked

Take a look at this partial list of exceptions again, and determine which ones are checked and unchecked.

For example, in DemoExc5A, the upperCase method throws an IndexOutOfBoundsException which is a descendant of RuntimeException and thus unchecked, and does not have to be caught:

public class DemoExc5A
{
	public static void main(String [] args)
	{
		System.out.println( upperCase("The", 2) );
		System.out.println( upperCase("orange", 25) );
		System.out.println( upperCase("cat", 1) );
		System.out.println( upperCase("was", 3) );
		System.out.println( upperCase("climbing.", 4) );

		System.out.println("Finishing up the application.");
		System.out.println("Attempted to convert five words.");
	}

	public static String upperCase(String in, int number)
	{
		if (number > in.length())
			throw new IndexOutOfBoundsExceptin("The value " +
				number + " is too large for " + in);

		String out = in.substring(0, number).toUpperCase() + 
				in.substring(number, in.length());
		return out;
	}
}
If we change upperCase to that it throws Exception (which is not a descendant of RuntimeException), then our program (renamed DemoExc5) will not compile:
public class DemoExc5
{
	public static void main(String [] args)
	{
		System.out.println( upperCase("The", 2) );
		System.out.println( upperCase("orange", 25) );
		System.out.println( upperCase("cat", 1) );
		System.out.println( upperCase("was", 3) );
		System.out.println( upperCase("climbing.", 4) );

		System.out.println("Finishing up the application.");
		System.out.println("Attempted to convert five words.");
	}

	public static String upperCase(String in, int number)
	{
		if (number > in.length())
			throw new Exception("The value " +
				number + " is too large for " + in);

		String out = in.substring(0, number).toUpperCase() + 
				in.substring(number, in.length());
		return out;
	}
}

The compiler generates the following error message:
DemoExc5.java:18: unreported exception java.lang.Exception; must be caught or 
  declared to be thrown
			throw new Exception("The value " +
                        ^
1 error
The upperCase method must either catch the checked exception or announce that it is going to throw it along. Here we get rid of the error in upperCase by adding the "throws" clause to the method header line:
public class DemoExc6
{
	public static void main(String [] args)
	{
		System.out.println( upperCase("The", 2) );
		System.out.println( upperCase("orange", 25) );
		System.out.println( upperCase("cat", 1) );
		System.out.println( upperCase("was", 3) );
		System.out.println( upperCase("climbing.", 4) );

		System.out.println("Finishing up the application.");
		System.out.println("Attempted to convert five words.");
	}

	public static String upperCase(String in, int number) throws Exception
	{
		if (number > in.length())
			throw new Exception("The value " +
				number + " is too large for " + in);

		String out = in.substring(0, number).toUpperCase() + 
				in.substring(number, in.length());
		return out;
	}
}

This causes three similar error messages to be generated by the compiler for the main method:

DemoExc6.java:5: unreported exception java.lang.Exception; must be caught or 
  declared to be thrown
		System.out.println( upperCase("The", 2) );
                                             ^
DemoExc6.java:6: unreported exception java.lang.Exception; must be caught or 
  declared to be thrown
		System.out.println( upperCase("orange", 25) );
                                             ^
DemoExc6.java:7: unreported exception java.lang.Exception; must be caught or 
  declared to be thrown
		System.out.println( upperCase("cat", 1) );
                                             ^
DemoExc6.java:8: unreported exception java.lang.Exception; must be caught or 
  declared to be thrown
		System.out.println( upperCase("was", 3) );
                                             ^
DemoExc6.java:9: unreported exception java.lang.Exception; must be caught or 
  declared to be thrown
		System.out.println( upperCase("climbing.", 4) );
                                             ^
5 errors
This can be fixed by having main use the "throws" clause:
public class DemoExc7
{
	public static void main(String [] args) throws Exception
	{
		System.out.println( upperCase("The", 2) );
		System.out.println( upperCase("orange", 25) );
		System.out.println( upperCase("cat", 1) );
		System.out.println( upperCase("was", 3) );
		System.out.println( upperCase("climbing.", 4) );

		System.out.println("Finishing up the application.");
		System.out.println("Attempted to convert five words.");
	}

	public static String upperCase(String in, int number) throws Exception
	{
		if (number > in.length())
			throw new Exception("The value " +
				number + " is too large for " + in);

		String out = in.substring(0, number).toUpperCase() + 
				in.substring(number, in.length());
		return out;
	}
}

The program will compile and run. Unfortunately, any thrown exceptions get thrown by main and abnormally end the program:
THe
Exception in thread "main" java.lang.Exception: The value 25 is too large for orange
	at DemoExc7.upperCase(DemoExc7.java:18)
	at DemoExc7.main(DemoExc7.java:6)

It is better to handle the exception and not allow an abnormal termination of the program:

public class DemoExc8
{
	public static void main(String [] args) throws Exception
	{
		try
		{
			System.out.println( upperCase("The", 2) );
			System.out.println( upperCase("orange", 25) );
			System.out.println( upperCase("cat", 1) );
			System.out.println( upperCase("was", 3) );
			System.out.println( upperCase("climbing.", 4) );
		}
		catch (Exception e)
		{
			System.err.println("***>> " + e);
		}

		System.out.println("Finishing up the application.");
		System.out.println("Attempted to convert five words.");
	}

	public static String upperCase(String in, int number) throws Exception
	{
		if (number > in.length())
			throw new Exception("The value " +
				number + " is too large for " + in);

		String out = in.substring(0, number).toUpperCase() + 
				in.substring(number, in.length());
		return out;
	}
}
This application will yield the following output:
THe
***>> java.lang.Exception: The value 25 is too large for orange
Finishing up the application.
Attempted to convert five words.

Finally

If it is possible that an thrown exception can get by a line of code that CANNOT be skipped, then you can put that line of code in a "finally" clause to guarantee that the line is executed. The finally clause must be associated with a "try" clause. Either there is no attempt to catch the exception:

	public static void two() throws Exception
	{
		try
		{
			System.out.println("Start two");
			three();
			System.out.println("End two");
			System.out.println("Special line in two");
		}

		finally 
		{ 
			System.out.println("Special in two"); 
		}
	}
Or the catch block might not catch the thrown exception (because the catch block's reference does not match the thrown exception or any of the thrown excpetion's superclasses):
	public static void someMethod() throws IOException
	{
		try
		{
			System.out.println( upperCase("The", 2) );
			System.out.println( upperCase("orange", 25) );

			openSomeFiles();  // this method might cause IOException

			System.out.println("Finishing up the application.");
			System.out.println("Attempted to convert five words.");
		}
		catch (IndexOutOfBoundsException ioe)
		{
			System.out.println("Bad index");
		}
		finally
		{
			System.out.println("Never gets skipped.");
			System.out.println("Ever.");
		}
	}

Catch an exception or let it travel on

Using the information described in the above sections, answer the following questions.

  1. Will the following code compile? If "no", what is the error message generated by the compiler? If "yes", what is the output when the program is run?
    public class DemoExc9
    {
    	public static void main(String [] args) throws Exception
    	{
    		System.out.println("Start main");
    		one();
    		System.out.println("End main");
    	}
    
    	public static void one()
    	{
    		System.out.println("Start one");
    		two();
    		System.out.println("End one");
    	}
    
    	public static void two()
    	{
    		System.out.println("Start two");
    		three();
    		System.out.println("End two");
    	}
    
    	public static void three()
    	{
    		System.out.println("Start three");
    		four();
    		System.out.println("End three");
    	}
    
    	public static void four()
    	{
    		try
    		{
    			System.out.println( upperCase("The", 2) );
    			System.out.println( upperCase("orange", 25) );
    			System.out.println( upperCase("cat", 1) );
    			System.out.println( upperCase("was", 3) );
    			System.out.println( upperCase("climbing.", 4) );
    		}
    		catch (Exception e)
    		{
    			System.out.println("***>> " + e);
    		}
    
    		System.out.println("Finishing up the application.");
    		System.out.println("Attempted to convert five words.");
    	}
    
    	public static String upperCase(String in, int number) throws Exception
    	{
    		if (number > in.length())
    			throw new Exception("The value " +
    				number + " is too large for " + in);
    
    		String out = in.substring(0, number).toUpperCase() + 
    				in.substring(number, in.length());
    		return out;
    	}
    }
    
    
  2. Will the following code compile? If "no", what is the error message generated by the compiler? If "yes", what is the output when the program is run?
    public class DemoExc10
    {
    	public static void main(String [] args) throws Exception
    	{
    		System.out.println("Start main");
    		one();
    		System.out.println("End main");
    	}
    
    	public static void one()
    	{
    		System.out.println("Start one");
    		two();
    		System.out.println("End one");
    	}
    
    	public static void two()
    	{
    		System.out.println("Start two");
    		try
    		{
    			three();
    		}
    		catch (Exception e)
    		{
    			System.out.println("***>> " + e);
    		}
    		System.out.println("End two");
    	}
    
    	public static void three() throws Exception
    	{
    		System.out.println("Start three");
    		four();
    		System.out.println("End three");
    	}
    
    	public static void four() throws Exception
    	{
    		System.out.println( upperCase("The", 2) );
    		System.out.println( upperCase("orange", 25) );
    		System.out.println( upperCase("cat", 1) );
    		System.out.println( upperCase("was", 3) );
    		System.out.println( upperCase("climbing.", 4) );
    
    		System.out.println("Finishing up the application.");
    		System.out.println("Attempted to convert five words.");
    	}
    
    	public static String upperCase(String in, int number) throws Exception
    	{
    		if (number > in.length())
    			throw new Exception("The value " +
    				number + " is too large for " + in);
    
    		String out = in.substring(0, number).toUpperCase() + 
    				in.substring(number, in.length());
    		return out;
    	}
    }
    
  3. Will the following code compile? If "no", what is the error message generated by the compiler? If "yes", what is the output when the program is run?
    public class DemoExc11
    {
    	public static void main(String [] args) throws Exception
    	{
    		System.out.println("Start main");
    		one();
    		System.out.println("End main");
    	}
    
    	public static void one()
    	{
    		System.out.println("Start one");
    		two();
    		System.out.println("End one");
    	}
    
    	public static void two()
    	{
    		System.out.println("Start two");
    		three();
    		System.out.println("End two");
    	}
    
    	public static void three()
    	{
    		System.out.println("Start three");
    		four();
    		System.out.println("End three");
    	}
    
    	public static void four()
    	{
    		System.out.println( upperCase("The", 2) );
    		System.out.println( upperCase("orange", 25) );
    		System.out.println( upperCase("cat", 1) );
    		System.out.println( upperCase("was", 3) );
    		System.out.println( upperCase("climbing.", 4) );
    
    		System.out.println("Finishing up the application.");
    		System.out.println("Attempted to convert five words.");
    	}
    
    	public static String upperCase(String in, int number) throws Exception
    	{
    		if (number > in.length())
    			throw new Exception("The value " +
    				number + " is too large for " + in);
    
    		String out = in.substring(0, number).toUpperCase() + 
    				in.substring(number, in.length());
    		return out;
    	}
    }
    
    
  4. Will the following code compile? If "no", what is the error message generated by the compiler? If "yes", what is the output when the program is run?
    public class DemoExc12A
    {
    	public static void main(String [] args) throws Exception
    	{
    		System.out.println("Start main");
    		one();
    		System.out.println("End main");
    	}
    
    	public static void one()
    	{
    		System.out.println("Start one");
    		two();
    		System.out.println("End one");
    	}
    
    	public static void two()
    	{
    		System.out.println("Start two");
    		three();
    		System.out.println("End two");
    	}
    
    	public static void three()
    	{
    		System.out.println("Start three");
    		four();
    		System.out.println("End three");
    	}
    
    	public static void four()
    	{
    		System.out.println( upperCase("The", 2) );
    		System.out.println( upperCase("orange", 25) );
    		System.out.println( upperCase("cat", 1) );
    		System.out.println( upperCase("was", 3) );
    		System.out.println( upperCase("climbing.", 4) );
    
    		System.out.println("Finishing up the application.");
    		System.out.println("Attempted to convert five words.");
    	}
    
    	public static String upperCase(String in, int number)
    	{
    		if (number > in.length())
    			throw new RuntimeException("The value " +   // CHANGE!
    				number + " is too large for " + in);
    
    		String out = in.substring(0, number).toUpperCase() + 
    				in.substring(number, in.length());
    		return out;
    	}
    }
    
  5. Will the following code compile? If "no", what is the error message generated by the compiler? If "yes", what is the output when the program is run?
    public class DemoExc12
    {
    	public static void main(String [] args) throws Exception
    	{
    		System.out.println("Start main");
    		one();
    		System.out.println("End main");
    	}
    
    	public static void one()
    	{
    		System.out.println("Start one");
    		two();
    		System.out.println("End one");
    	}
    
    	public static void two()
    	{
    		System.out.println("Start two");
    		try
    		{
    			three();
    		}
    		catch (Exception e)
    		{
    			System.out.println("***>> " + e);
    		}
    		System.out.println("End two");
    	}
    
    	public static void three() throws Exception
    	{
    		System.out.println("Start three");
    		four();
    		System.out.println("End three");
    	}
    
    	public static void four() throws Exception
    	{
    		try
    		{
    			System.out.println( upperCase("The", 2) );
    			System.out.println( upperCase("orange", 25) );
    			System.out.println( upperCase("cat", 1) );
    			System.out.println( upperCase("was", 3) );
    			System.out.println( upperCase("climbing.", 4) );
    
    			System.out.println("Finishing up the application.");
    			System.out.println("Attempted to convert five words.");
    		}
    		finally
    		{
    			System.out.println("Never gets skipped.");
    			System.out.println("Ever.");
    		}
    	}
    
    	public static String upperCase(String in, int number) throws Exception
    	{
    		if (number > in.length())
    			throw new Exception("The value " +
    				number + " is too large for " + in);
    
    		String out = in.substring(0, number).toUpperCase() + 
    				in.substring(number, in.length());
    		return out;
    	}
    }
    
    
  6. Will the following code compile? If "no", what is the error message generated by the compiler? If "yes", what is the output when the program is run?
    public class DemoExc13
    {
    	public static void main(String [] args) throws Exception
    	{
    		System.out.println("Start main");
    		one();
    		System.out.println("End main");
    	}
    
    	public static void one()
    	{
    		System.out.println("Start one");
    		try
    		{
    			two();
    		}
    		catch (Exception e)
    		{
    			System.out.println("***>> " + e);
    		}
    		System.out.println("End one");
    	}
    
    	public static void two()
    	{
    		try
    		{
    			System.out.println("Start two");
    			three();
    			System.out.println("End two");
    			System.out.println("Special line in two");
    		}
    
    		finally 
    		{ 
    			System.out.println("Special in two"); 
    		}
    	}
    
    	public static void three() throws Exception
    	{
    		System.out.println("Start three");
    		four();
    		System.out.println("End three");
    	}
    
    	public static void four() throws Exception
    	{
    		System.out.println( upperCase("The", 2) );
    		System.out.println( upperCase("orange", 25) );
    		System.out.println( upperCase("cat", 1) );
    		System.out.println( upperCase("was", 3) );
    		System.out.println( upperCase("climbing.", 4) );
    
    		System.out.println("Finishing up the application.");
    		System.out.println("Attempted to convert five words.");
    	}
    
    	public static String upperCase(String in, int number) throws Exception
    	{
    		if (number > in.length())
    			throw new Exception("The value " +
    				number + " is too large for " + in);
    
    		String out = in.substring(0, number).toUpperCase() + 
    				in.substring(number, in.length());
    		return out;
    	}
    }

The Path of an Uncaught Exception

If an exception occurs in a method, and that method does not catch the exception, then the exception travels back to where that method was called (and if it is not caught by the calling method, it then travels back to where that method was called). The next couple of figures will illustrate this. First, lets look a program without any exceptions or exception handling, just to see the normal program flow:

public class DemoExc
{
   public static void main(String [] args)
   {
      ShowPath sp = new ShowPath();
      sp.one();
   }
}

class ShowPath
{
   void one()
   {
      System.out.println("Top of one");
      two();
      System.out.println("Bottom of one");
   }

   void two()
   {
      System.out.println("Top of two");
      three();
      System.out.println("Bottom of two");
   }


   void three()
   {
      System.out.println("Three");
   }
}

The above program generates the following output:

Top of one
Top of two
Three
Bottom of two
Bottom of one

For example, if a number greater than 0.5 is generated by the random number generator in the following code:

public class DemoExc2
{
   public static void main(String [] args)
   {
      ShowPath sp = new ShowPath();
      sp.one();
   }
}

class ShowPath
{
   void one()
   {
      System.out.println("Top of one");   // 1
      two();  // 2
      System.out.println("Bottom of one");  // 3
   }

   void two()
   {
      System.out.println("Top of two");  // 4
      three();  // 5
      System.out.println("Bottom of two");  // 6
   }

   void three()
   {
      if (Math.random() > 0.5)  // 7
         throw new RuntimeException("Big random number");  // 8
      System.out.println("Three");  // 9
   }
}

About half the time the exception is not thrown and the output is:

Top of one
Top of two
Three
Bottom of two
Bottom of one

However, when the exception is thrown we get the following output:

Top of one
Top of two
Exception in thread "main" java.lang.RuntimeException: Big random number
	at ShowPath.three(DemoExc2.java:30)
    at ShowPath.two(DemoExc2.java:22)
    at ShowPath.one(DemoExc2.java:15)
    at DemoExc2.main(DemoExc2.java:6)

The first two lines of output show the what was printed before the exception occured. The remainder of the messages are printed by the Java Virtual Machine, indicating the path the exception took before it finally reached the main method, and uncaught, crashed the program. What occured was that the exception is thrown in the method three, it is not caught there and emits from where three was called at line marked "// 5" (notice that the "// 9" statement was skipped in three). The two method also does not catch the exception, so the exception travels back to where it was called a the line marked "// 2". The one method doesn't catch the exception, so it travels back to where one was called in main. The main method does not catch the exception, so the exception emits from main and crashes the program.

The exception can be caught anywhere along that path. For example:

public class DemoExc3
{
   public static void main(String [] args)
   {
      ShowPath sp = new ShowPath();
      sp.one();
   }
}

class ShowPath
{
   void one()
   {
      System.out.println("Top of one");
      try
      {
         two();
      }
      catch (RuntimeException exc)
      {
         System.out.println("Caught yeh!");
      }
      System.out.println("Bottom of one");
   }

   void two()
   {
      System.out.println("Top of two");
      three();
      System.out.println("Bottom of two");
   }

   void three()
   {
      if (Math.random() > 0.5)
         throw new RuntimeException("Big random number");
      System.out.println("Three");
   }
}

On the runs of the program DemoExc3 that generate an exception the output will look like this:

Top of one
Top of two
Caught yeh!
Bottom of one

Notice that "Bottom of three" and "Bottom of two" are skipped, but once the exception has been caught normal flow resumes and "Bottom of one" is reported.

More Notes On Using "finally"

If you have some instructions in a method that absolutely cannot be skipped, those instructions can be setup in a finally block. Code in a finally block is not skipped over by an uncaught exception. Note that a finally block has to be associated with a try block. In the code below, I've taken the DemoExc2 example from above, which did not catch the exception and let the exception travel to main and crash the program, and added try and finally blocks to the the two method.

public class DemoExc5
{
   public static void main(String [] args)
   {
      ShowPath sp = new ShowPath();
      sp.one();
   }
}

class ShowPath
{
   void one()
   {
      System.out.println("Top of one");
      two();
      System.out.println("Bottom of one");
   }

   void two()
   {
      try
      {
         System.out.println("Top of two");
         three();
         System.out.println("Bottom of two");
      }
      finally
      {
         System.out.println("Can't be skipped!");
      }
   }

   void three()
   {
      if (Math.random() > 0.5)
         throw new RuntimeException("Big random number");
      System.out.println("Three");
   }
}

Here is the output from the above program (on a run that yielded a random number greater than 0.5):

Top of one
Top of two
Can't be skipped!
Exception in thread "main" java.lang.RuntimeException: Big random number
	at ShowPath.three(DemoExc2.java:37)
    at ShowPath.two(DemoExc2.java:24)
    at ShowPath.one(DemoExc2.java:15)
    at DemoExc2.main(DemoExc2.java:6)

When a "try" Block Yields More than One Kind of Exception

Let's assume that we want to try to call the mythical methods funA(), funB() and funC(). And let's assume that these methods throw the following Exceptions:

  • funA(): FileNotFoundException
  • funB(): InterruptedException
  • funC(): ArithmeticException

If we call all three of these methods in one try block, there are several ways we can arrange to catch (or not to catch) thrown exceptions. One way is the following:

	public void init()	
	{
		someMethod1()
	}

	public void someMethod1()
	{
		someMethod2();
	}

	public void someMethod2()
	{
		someMethod3();
	}

	public void someMethod3()
	{
		try 
		{
			funA();
			funB();
			funC();
		}
		catch(Exception e)
		{
			showStatus("An error occured");
		}
	}

Or, we could do the following:

	public void init()
	{
		someMethod1()
	}

	public void someMethod1()
	{
		someMethod2();
	}

	public void someMethod2()
	{
		someMethod3();
	}

	public void someMethod3()
	{
		try 
		{
			funA();
			funB();
			funC();
		}
		catch(FileNotFoundException fnfExc)  // A
		{
			showStatus("File not found!");
		}
		catch(InterruptedException iExc)     // B
		{
			showStatus("Interrupted!");
		}
		catch(ArithmeticException aExc)      // C
		{
			showStatus("Arithmetic exception!");
		}
	}

Exercises

Looking at the two above examples:
  1. Is one way better than the other? If so, why?
  2. Looking at only the second example:
    1. If we deleted the catch block labeled "A", what would happen?
    2. If we deleted the catch block labeled "B", what would happen?
    3. If we deleted the catch block labeled "C", what would happen?
  3. What would happen if you removed the "try" and all of the corresponding "catch" blocks, as shown in the example below?
    	public void init()
    	{
    		someMethod1()
    	}
    
    	public void someMethod1()
    	{
    		someMethod2();
    	}
    
    	public void someMethod2()
    	{
    		someMethod3();
    	}
    
    	public void someMethod3()
    	{
    		funA();
    		funB();
    		funC();
    	}
    
  4. What would happen if you changed the ordering of the catches from "A B C" to "C B A"?

Misc.

  1. Variables declared in the try block are not available outside the try block>
    1. What are the implications of this?
    2. How can you avoid that problem?
  2. You can have several catches after a single try
    1. What do you get by having more than one catch block?
    2. Which block actually catches the exception?
  3. If your a method does not catch a checked exception, what do you have to do to the method?

The instanceof Operator

You can use the "instanceof" operator to make this catch

		catch(Exception e)
		{
			showStatus("An error occured");
		}
act more like this catch
		catch(FileNotFoundException fnfExc)  // A
		{
			showStatus("File not found!");
		}
		catch(InterruptedException iExc)     // B
		{
			showStatus("Interrupted!");
		}
		catch(ArithmeticException aExc)      // C
		{
			showStatus("Arithmetic exception!");
		}
The instanceof operator returns true or false for queries such as
		if (e instanceof InterruptedException)

How could you transform the generic "catch (Exception e)" using this operator?

Applet Examples

Here is an alternative introduction to exceptions utilizing applets.

Home - About Us
Copyright © 2006 by Kiowok, Ann Arbor, Michigan, USA