taylorialcom/ Miscellaneous

Exception Handling

The exception handling features in the Java language provide a mechanism for gracefully recovering from a wide variety of unexpected situations in your code.

Even if you've never heard of exceptions in Java, if you do much Java software development, you've likely encountered an exception of some sort. Program "crashes" are often the result of "an exception being thrown." When this happens, something like this is displayed to the console:

Exception in thread "main" java.lang.NullPointerException
  at lecture.Driver.main(Driver.java:19)

The exception handling features in the Java language provide a mechanism for gracefully recovering from a wide variety of unexpected situations in your code.

In the first example, I tried to call a method using a reference that was assigned to null. Since it wasn't referring to an actual object, it was not possible to execute the method. At that point, the normal flow of the program is interrupted by an exception being thrown. In this case, I didn't do anything to handle the exception. As a result, the exception was thrown all the way back the the JVM (Java Virtual Machine) which then displayed the stack trace.

The stack trace is a list of all of the method calls that took place before the exception was thrown. In this case, the exception was thrown from main (on line 19).

Here is another example of an exception being thrown:

Exception in thread "main" java.lang.NumberFormatException: For input string: "not an integer"
  at java.lang.NumberFormatException.forInputString(Unknown Source)
  at java.lang.Integer.parseInt(Unknown Source)
  at java.lang.Integer.parseInt(Unknown Source)
  at edu.msoe.cs1021.taylor.Horse.calculatePrice(Horse.java:134)
  at edu.msoe.cs1021.taylor.Lab4.displayMarketPrice(Lab4.java:74)
  at edu.msoe.cs1021.taylor.Lab4.main(Lab4.java:61)

In this case, I called Integer.parseInt with "not an integer" as the argument. Of course, this cannot be converted/parsed into an integer. So what should we do? One option would be to just ignore the error (silently fail). If we did this, the parseInt method would still need to return something. What should we return? Another option would be to just give up and stop the program (that's essentially what happened here).

If you look at the stack trace displayed above, you can see that the exception was thrown in the Integer.parseInt method which was called by the Horse.calculatePrice which was called by the Lab4.displayMarketPrice method which was called by the Lab4.main method. The stack trace also includes the line numbers on which the each method was called. This helps the developer track down the source of the exception.

Depending on the design of our application, we may want to correct for this incorrect behavior in the Horse.calculatePrice method or Lab4.displayMarketPrice method or the Lab4.main method. The exception handling mechanism in Java provides just the flexibility we need in order to handle error conditions that may be encountered (bad user input, missing file, no network connection, etc...) in a place that makes sense to us.

Exceptions

To summarize the discussion above:

int x = Integer.parseInt("1.234");

Consider the following code snippet:

String input = JOptionPane.showInputDialog(null, "How old are you (in years)");
int age;
try {
  age = Integer.parseInt(input);
  JOptionPane.showMessageDialog(null, "I'm guessing you'll be " + (age+1) + " next year");
} catch (NumberFormatException e) {
  JOptionPane.showMessageDialog(null, "Error!  You should enter an integer value");
}

If we enter something other than an integer, the program will display the error message, otherwise it will "guess" how old the user will be next year.

try block

catch blocks

Types of Exceptions

After studying the Throwable, Error, and Exception classes we can conclude that:

Exception Class Hierarchy
Figure 1: Exception Class Hierarchy

Handling Exceptions

catch (Exception e) {
  // ...
}

since Exception is a superclass of NumberFormatException.

Recapping

Consider the following code:

String input = JOptionPane.showInputDialog(null, "How old are you (in years)");
int age;
try {
  age = Integer.parseInt(input);
  JOptionPane.showMessageDialog(null, "I'm guessing you'll be " + (age+1) + " next year");
} catch (NumberFormatException e) {
  JOptionPane.showMessageDialog(null, "Error!  You should enter an integer value");
} catch (RuntimeException e) {
  JOptionPane.showMessageDialog(null, "Error!  Some runtime exception other than NumberFormatException was thrown");
  JOptionPane.showMessageDialog(null, "Hint: " + e.getMessage());
  return;
}

JOptionPane.showMessageDialog(null, "No worries.  Either way we'll continue on with our program");

throw statement

throw new Exception("Info about the exception");

Modifying the previous code to throw an exception if the user entered an age greater than 120 would look like this:

String input = JOptionPane.showInputDialog(null, "How old are you (in years)");
int age;
try {
  age = Integer.parseInt(input);
  if(age>120) {
    throw new Exception("Out of bounds");
  }
  JOptionPane.showMessageDialog(null, "I'm guessing you'll be " + (age+1) + " next year");
} catch (NumberFormatException e) {
  JOptionPane.showMessageDialog(null, "Error!  You should enter an integer value");
} catch (RuntimeException e) {
  JOptionPane.showMessageDialog(null, "Error!  Some runtime exception other than NumberFormatException was thrown");
  JOptionPane.showMessageDialog(null, "Hint: " + e.getMessage());
  return;
}

JOptionPane.showMessageDialog(null, "No worries.  Either way we'll continue on with our program");

Exception throwers

Unchecked Exception

void someMethod() throws IOException {
  // ...
}

The finally Block