knowledge-kitchen

Object-Orientation - Exception Handling (in Java)

Beginner knows rules, but veterans know exceptions.

–Amit Kalantri, in Wealth of Words

  1. Overview
  2. Exception Handling
  3. Custom Exceptions
  4. Conclusions

Overview

Concept

An exception is a disruption to the normal control flow of of a program.

Types

Exceptions are divided into two types, depending upon when they appear.

Exceptional lineage

The ancestry of Exception and Error objects is quite exceptional.

Throwable
   |
   |---> Exception
   |        |
   |        |---> IOException
   |        |           |
   |        |           |---> FileIOException
   |        |
   |        |---> RuntimeException
   |                    |
   |                    |---> NullPointerException
   |                    |
   |                    |---> IndexOutOfBoundsException
   |
   |---> Error

Why two types?

You may wonder why all exceptions aren’t checked by the compiler, so Java can avoid runtime crashes.

Net net

In conclusion, the Java people recommend the following:

Exception Handling

Options

Any method that includes code that might cause a checked exception to occur must handle that situation in one of two ways, in order to compile.

Example - the problem

For example, take a method that opens a file… this might cause a checked exception if the file being opened does not exist.

public void doSomething() {
  Scanner scn = new Scanner( new File( "foo.csv" ) );
  // .. imagine we do something useful with this file here ...
}

Example - the try/catch solution

One way to get the code to compile would be to surround the code of concern within a try/catch block.

public void doSomething() {

  try {
    // attempt to open the file... this may or may not fail
    Scanner scn = new Scanner( new File( "foo.csv" ) );
    // .. imagine we do something useful with this file here ...
  }
  catch (FileNotFoundException e) {
    // handle the situation in which the file was not found
    System.out.println("So sorry, we couldn't open the file.");
    // put whatever you want to do in this situation here.
  }
}

Example - the throws solution

An alternative way to get that code to compile would have been to declare that the method throws an exception.

public void doSomething() throws FileNotFoundException {
  Scanner scn = new Scanner( new File( "foo.csv" ) );
  // .. imagine we do something useful with this file here ...
}

Example - the throws solution (continued)

Let’s imagine another method that calls our doSomething method.

public void anotherMethod() {
  doSomething(); // call the method that might trigger an exception
}

Example - the throws solution (continued again)

Here are the two options for our anotherMethod() in order for it to compile.

// the try/catch way
public void anotherMethod() {
  try {
    doSomething(); // call the method that might trigger an exception
  }
  catch (FileNotFoundException e) {
    System.out.println("So sorry, we couldn't open the file.");
    // put whatever you want to do in this situation here.
  }
}

Try it!… - or - try this:…

// the throws way
public void anotherMethod() throws FileNotFoundException {
  doSomething();
}

Custom Exceptions

Concept

While the Java API comes with exception types useful for many common situations, it is possible to build one’s own exception types.

Subclassing Exception

Here is an example of a custom exception type, useful for the situation where a virtual person sips a burning hot virtual cup of coffeee.

public class BurnedMouthException extends Exception {
  // .. put any code you want in here.
}

Throw and throws

Here is an example of the sip() method in our Person class that might throw one of our custom exceptions if the Coffee object is burning hot.

public class Person {

  public void sip(Coffee c) throws BurnedMouthException {
    // throw an exception if the temperature is too hot
    if ( c.getTemperature("Farenheit") > 113 ) {
      throw new BurnedMouthException();
    }
  }
}

Throwing multiple possible exceptions

It’s perfectly possible for a method to potentially throw more than one type of exception.

public void sip(Coffee c) throws BurnedMouthException, OutOfCoffeeException {

    // throw an exception if the temperature is too hot
    if ( c.getTemperature("Farenheit") > 113 ) {
      throw new BurnedMouthException();
    }

    // throw an exception if the coffee is empty
    else if ( c.coffeeRemaining() == 0 ) {
      throw new OutOfCoffeeException();
    }

}

Handling exceptions

As we have already learned, any other method that calls this sip() method must handle the possibility of a checked exception occurring in one of two ways. Here is a try/catch solution:

try {
  // let's imagine that we have Person object person and Coffee object coffee
  person.sip(coffee);
}
catch (BurnedMouthException e) {
  // do something in response to this exception being thrown
}
catch (OutOfCoffeeException e) {
  // do something in response to this exeption being thrown
}

Handling exceptions (continued)

Alternatively, of course, this method could have declared that it throws the two exceptions that the sip() method might throw, thereby passing the buck to any method that calls it.

public static void main(String[] args) throws BurnedMouthException, OutOfCoffeeException {

    // imagine that we have Person object person and Coffee object coffee already instantiated

    // have the person take a sip
    person.sip(coffee);

}

Conclusions

Like function arguments and return values, checked exceptions are yet another mechanism by which messages are passed from one part of a Java program to another.