Skip to content
Theory · Exceptions · lesson 1 of 12

What an exception is

What you'll learn

What you'll learn:

  • read an exception message and use the stack trace to find the line where the error happened;
  • catch exceptions with try and catch and run must-run code in finally;
  • tell checked exceptions from unchecked ones and throw your own with throw;
  • close resources automatically with try-with-resources.

Picture an office building where work flows from the top down. The director on the top floor gives a task to the department one floor below. The department passes part of the work to the workshop further down and waits for it to return the result.

Suddenly the fire alarm goes off in the workshop. If someone there knows what to do, they answer the alarm, and work goes on. If no one does, the workshop drops its work, and the alarm sounds one floor up, with whoever gave it the task. And so on, floor after floor, up the stairs, until someone answers. If even the director does not answer, the whole building is evacuated.

A Java program works the same way. The main method hands work to other methods, and they call the next ones. When a method cannot finish its work, the alarm goes off: an exception. You have already met such alarms:

  • ArithmeticException: integer division by zero;
  • ArrayIndexOutOfBoundsException: an index past the end of an array;
  • NullPointerException: a field or method through null;
  • ClassCastException: a cast to a class the object does not belong to;
  • NumberFormatException: Integer.parseInt got a string that is not a whole number.

Each time the program compiled and then stopped when it ran: no one answered the alarm, so the whole program was "evacuated". In this theme you will learn to answer the alarm. But first, let's see exactly what Java reports when a program stops.

An exception is an object

Take a program three floors high: main calls report, and report calls average, which divides a sum by a count.

JAVA
public class Main {
    static int average(int sum, int n) {
        return sum / n;
    }

    static void report(int sum, int n) {
        System.out.println("Average: " + average(sum, n));
    }

    public static void main(String[] args) {
        report(10, 2);
        report(10, 0);
        System.out.println("Done");
    }
}

Let's run it:

TEXT
Average: 5
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Main.average(Main.java:3)
	at Main.report(Main.java:7)
	at Main.main(Main.java:12)

Let's go through what happened:

  1. report(10, 2) calls average(10, 2), gets 5 and prints Average: 5.
  2. report(10, 0) calls average(10, 0), and the division 10 / 0 has no result.
  3. The JVM creates an object of the class ArithmeticException and throws it. The method average ends at once, without return.
  4. report never prints its line, and main never reaches Done: the program stops.

An exception is more than text on the screen: it is an object. It has a class, such as ArithmeticException, and a message, here / by zero. To throw an exception means to create such an object and break the normal flow of the program.

The first line: what happened

The first line of the message answers the question "what happened":

  • Exception in thread "main": the exception happened in the program's main thread, the one that runs main;
  • java.lang.ArithmeticException: the full name of the exception's class, the package java.lang and the class itself;
  • / by zero: the message with the details, a division by zero.

Often the class name alone tells you everything: ArithmeticException is an arithmetic error, NullPointerException means a null turned up somewhere.

The stack trace: where it happened

The lines that start with at are called the stack trace. Each of them is one unfinished call from the call stack you met in the theme on methods. Read the stack trace from the top down:

  1. at Main.average(Main.java:3): the class Main, the method average, the file Main.java, line 3. This is where the exception was thrown.
  2. at Main.report(Main.java:7): average was called from the method report, from line 7.
  3. at Main.main(Main.java:12): and report was called from main, from line 12.

A stack trace is like the fire alarm's log. The first entry is the floor where the sensor went off, below it each floor on the way up, and last the director main.

In an interview you may be shown a stack trace and asked where the error is. Start with the first at line: that is where the exception was thrown, and the lines below show who called whom.

Here the building picture is imprecise. A real siren is heard all over the house, but an exception travels only along the chain of unfinished calls. The first call report(10, 2) had already returned by then, so it is not in the stack trace.

Common mistake

The stack trace does not start with your code, and people look for the error inside Java itself:

JAVA
String text = "12a";
int n = Integer.parseInt(text); // ✗
System.out.println(n + 1);
TEXT
Exception in thread "main" java.lang.NumberFormatException: For input string: "12a"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
	at java.base/java.lang.Integer.parseInt(Integer.java:565)
	at java.base/java.lang.Integer.parseInt(Integer.java:662)
	at Main.main(Main.java:4)

The first three at lines lead inside the standard library: the prefix java.base/ says so. There is no error in the library. The method parseInt honestly reported that the string "12a" is not a whole number and threw the exception from inside itself.

Look for the first line with your own class: at Main.main(Main.java:4). That is your call to parseInt; in the file, two more lines come before this fragment, the headers of the class and of the method main. The call is what needs fixing: pass parseInt only a whole number.

Key points

  • An exception is an object with a class and a message; the JVM throws it when the program cannot go on.
  • A thrown exception ends its method, and then every calling method; if no one answers the alarm, the program stops.
  • The first line of the message names the exception's class and its message, and the at lines are the stack trace.
  • Read a stack trace from the top: the first at line is where the exception was thrown, and your own error is in the first line with your class.