Keywords: current

Next: 1.11.3 Exception Handling Up: 1.11 Unusual Situations versus Previous: 1.11.1 A Motivating Example

## 1.11.2 Using Java Exceptions

A Java exception is an object of type `Exception`, which is a built-in Java class. There are two basic forms of exceptions that can occur during Java program execution:

1. Unchecked exceptions, which extend the class `RuntimeException`, usually signal a program coding error.
2. Checked exceptions, which extend the class `Exception` but not the class `RuntimeException`, signal unusual but legal conditions that require deviation from the normal flow of control.

When an `EvalVisitor` encounters a `Var` not bound in `Env`, it has detected an error in the input expression. If the Arithmetic Expression evaluator is being used in a larger program that can prompt the user for corrected input, then such an input error should be handled as part of valid program execution. It does not indicate a coding error in the Arithmetic Expression evaluator. Hence, when an `EvalVisitor` encounters an unbound exception, it should throw a checked exception, which the larger program can intercept and interpret, printing an error message such as

> `I'm sorry, that's not a valid expression`

and prompt the user for corrected input with a message like

> `Please enter a valid expression:`

Java requires an explicit `throws` clause in the header for any method that can generate a checked exception, directly or indirectly by invoking another method. The `EvalVisitor` class defined above will return `null` or generate a

> `NullPointerException`

if it encounters an unbound variable. The `lookup` method will return `null` as the value of an unbound variable. Any subsequent attempt to use such a value as a `Const` (e.g., in computing a `Sum`) will generate a

> `NullPointerException`

. Since this exception is unchecked, it does not need to be declared in `throw` clauses.

If we rewrite `lookup` to throw a checked `UnboundException` instead of returning `null`, the change has a dramatic impact on the rest of the program. The revised code appears below:

    class UnboundException extends Exception {
      UnboundException(String name) {
        super("Variable " + name + " is unbound");
        String varName = name;
      }
    }

    class Env {
      abstract Const lookup(String name) throws UnboundException};
    }

    class Empty extends Env {
      Const lookup(String name) throws UnboundException} {
        throw UnboundException(name);
      }
    }

    class Cons extends Env {
      String firstName;
      Const firstVal;
      Env rest;

      Cons(String name, Const val, Env env) {
        firstName = name;
        firstVal = val;
        rest = env;
      }

      Const lookup(String name) throws UnboundException} {
        if (name.equals(firstName)) return firstVal;
        else return rest.lookup(name);
      }
    }

    class EvalVisitor implements Visitor {
      Env env;
      Object forConst(Const c) { return c; }
      Object forSum(Sum s) throws UnboundException { ... };
      Object forProd(Prod p) throws UnboundException { ... };
      Object forVar(Var v) throws UnboundException { ... };
      Object forLet(Let l) throws UnboundException { ... };
      }
    }

    interface Visitor {
      Object forConst(Const c) { return c; }
      Object forSum(Sum s) throws UnboundException;
      Object forProd(Prod p) throws UnboundException;
      Object forVar(Var v) throws UnboundException;
      Object forLet(Let l) throws UnboundException;
    }

The preceding code cleanly handles input errors, but it pollutes the signatures of nearly all of the `for` methods in the class `Visitor` and its descendants. In this case, an unchecked exception is preferable. The code for this variation is identical the code above except for the `extends` clause in the definition of class `UnboundException` and the elimination of all `throws` clauses in `for` methods.

Checked exceptions and polymorphic programming do not mix well. Consequently, it should not be surprising that the Java libraries use unchecked exceptions far more than they use checked exceptions. Our advice is use checked exceptions to signal unusual conditions in code that does not involve polymorphism. If polymorphism is present, use unchecked exceptions instead.

Next: 1.11.3 Exception Handling Up: 1.11 Unusual Situations versus Previous: 1.11.1 A Motivating Example