Skip to content
Lesson 15 of 15

Step 1 of 7 · Reading · ~3 min

Learn

Inheritance and Interfaces

Exception Handling

Programs meet bad input, missing data and impossible requests. Java reports these with exceptions: objects that interrupt normal flow and travel up the call stack until something handles them. By the end of this lesson you can catch the failures you expect, raise your own, order catch blocks correctly, and know which exceptions the compiler forces you to deal with.

try / catch / finally

for (String s : new String[]{"50", "150", "abc"}) {
    try {
        System.out.println(parsePercent(s));
    } catch (NumberFormatException ex) {
        System.out.println("not a number: " + ex.getMessage());
    } catch (IllegalArgumentException ex) {
        System.out.println("bad: " + ex.getMessage());
    }
}

Code that might fail goes in try. If it throws, Java skips the rest of the try block and runs the first catch whose type matches; if none matches the exception keeps travelling up. An optional finally block runs always, whether the try finished, threw, or even returned: that is the place for cleanup.

throw: raising an exception

static int parsePercent(String s) {
    int v = Integer.parseInt(s);            // may throw NumberFormatException
    if (v < 0 || v > 100) {
        throw new IllegalArgumentException("out of range: " + v);
    }
    return v;
}

throw creates an exception object and starts it travelling. For "50" this returns 50; for "150" the caller sees bad: out of range: 150; for "abc", parseInt itself throws and the message is For input string: "abc".

The hierarchy decides the order

Throwable
  Error                      (JVM-level problems: do not catch)
  Exception
    RuntimeException         (unchecked)
      IllegalArgumentException
        NumberFormatException
      ArithmeticException
      IndexOutOfBoundsException
      NullPointerException
    IOException, ...         (checked)

NumberFormatException is an IllegalArgumentException. A catch (IllegalArgumentException e) therefore also catches number-format errors. Because Java uses the first matching catch, put the more specific type first. Reverse them above and the compiler rejects the code ("exception NumberFormatException has already been caught"), since the second block could never run.

Checked and unchecked

  • Unchecked exceptions (RuntimeException and subclasses): NullPointerException, ArithmeticException (integer divide by zero), ArrayIndexOutOfBoundsException, NumberFormatException. Java does not force you to handle them.
  • Checked exceptions (other Exception subclasses, like IOException): the compiler requires the method to either catch them or declare throws in its signature.

Not every arithmetic problem is an exception: integer overflow wraps silently. Only integer division by zero throws.

Custom exceptions

static class LowStock extends Exception {
    private final int left;

    LowStock(String message, int left) {
        super(message);
        this.left = left;
    }

    int getLeft() { return left; }
}

static void ship(int stock, int want) throws LowStock {
    if (want > stock) {
        throw new LowStock("only " + stock + " left", stock);
    }
}

Extend Exception for a checked exception, RuntimeException for an unchecked one. A custom type lets callers catch exactly your failure, and can carry extra data.

try-with-resources

Objects that hold something open (files, scanners, connections) implement AutoCloseable. Declaring them in the parentheses of try closes them automatically, even if an exception is thrown:

try (Scanner in = new Scanner("12 x")) {
    int a = in.nextInt();
} catch (java.util.InputMismatchException e) {
    System.out.println("mismatch");
}

Common mistakes

  • Catching Exception to make errors disappear. It hides real bugs. Catch the type you can actually handle.
  • An empty catch block. The failure vanishes without a trace.
  • Wrong catch order, with the general type first.
  • Using exceptions for ordinary control flow. If you can check the condition with an if, do that.

Your exercise

Evaluate a list of small division expressions where the input may be broken in three different ways. Each kind of failure should be reported by its own catch, and one of them is deliberately an instance of another's parent type, so the order of your catch blocks matters.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…