Exception Handling


There is bound to be times when your code causes an error. Java refers to these as exceptions.

For example, in an earlier topic, we learned how to parse Strings into numbers:

		int iZipCode = Integer.parseInt(sZipCode);
It's possible that a user may try to pass non-numeric values for the zip code. This happens most commonly when the user used to be a typist, and types a lowercase 'l' instead of the number 1.

The program 'throws' an exception when it can't parse a string - the 'NumberFormatException'. If you suspect a line of code may throw an exception, the best thing to do is 'try' to 'catch' it.

			try {
				int iZipCode = Integer.parseInt(sZipCode);
			}
			catch (NumberFormatException nfe) {
				// code for exception handling goes here
			}
The 'NumberFormatException' is a runtime exception- it's not required to be caught. However, if you fail to catch it, the program will exit the method at the point where the exception occurred, skipping any other lines of code. With the try-catch in place, the program will exit the 'try' at the point where the error occurred, execute the code in the 'catch' block, then continue with any code following the 'catch' block.

In the next topic, we will start using methods that throw exceptions. For these cases, a try-catch for the specific exceptions is required. However, we still have the potential of the program throwing exceptions. If we only catch the exceptions thrown by a method, and not those thrown by a program, there may be other problems. Let's say we open a connection to a database inside of a try-catch. After the 'catch', we have a statement to close the connection. If, inside the 'try' block, a 'NumberFormatException' occurs that we don't catch, the program exits the method without ever executing the close command on the connection. There are two ways to handle this:

  1. Add second 'catch' for the 'NumberFormatException'
  2. Add a second 'catch' for 'Exception' - the catch all of exceptions

Best practices dictates that we try to catch specific exceptions first, and not rely solely on the catch all. One additional step we can take to tighten up our exception handling is the 'finally' clause. This is a block of code that is executed whether or not the try block completes normally, results in an exception, or exits the containing method. A finally clause is therefore useful as a cleanup mechanism.

		try {
			int iZipCode = Integer.parseInt(sZipCode);
		}
		catch (NumberFormatException nfe) {
			// code for exception handling goes here
		}
		catch (Exception e) {
			// code for exception handling goes here
		}
		finally {
			// cleanup code goes here
			// in particular, resource-releasing code
		}
We don't always want to catch exceptions.  If an error occurs in a component of a program, that component needs to let the program know that something happened. We do this by passing the exception from the component to the program.  This is called throwing the exception.

For example, let's say we have a component called "ZipCodeValidator" that has a public method called "isValid."

		public class ZipCodeValidator {
		
			public boolean isValid(String sZipCode) throws NumberFormatException {
				
				int iZipCode = Integer.parseInt(sZipCode);
				
				return true;
				
			}
		}
Because the method throws the exception, we don't need to catch it here.  It's the responsibility of the program to catch the exception.
	public class Address {
	
		public static void main(String args[]) {
		
			ZipCodeValidator zcv = new ZipCodeValidator();
			
			try {
				if ( zcv.isValid(args[0]) {
					System.out.println(args[0] + " is a valid zip code");
				} else {
					System.out.println(args[0] + " is NOT a valid zip code");
				}
			}
			catch (NumberFormatException nfe) {
				// code for exception handling goes here
			}

		}
	}
You will see a better example of this when we get to the lecture on JDBC.