"Hi, Amigo. We're going to have a very interesting lesson today. I'm going to tell you about exceptions. Exceptions are a special mechanism that lets us handle errors in the program. Here are some examples of errors that might occur in a program:

1. The program may try to write a file when the hard drive is completely full.

2. The program may try to call a method on a variable storing a null reference.

3. The program may try to divide a number by 0."

All these actions result in errors. Usually, the result is that the program immediately terminates, since it makes no sense to continue executing code in this case.

"Why?"

"Does it make sense to keep turning a wheel if the car has gone off the road and is falling from a cliff?"

"Should the program stop running, then?"

"Yes. At least, this is what used to happen. Any error caused the program to terminate."

"That's a very smart approach."

"But wouldn't it be better to try and continue running the program?"

"Yes. Suppose you typed a huge amount of text in Word and saved it. What if the save operation fails, but the program leads you to believe that everything is fine? And you go on typing. That would be stupid, wouldn't it?"

"Yep."

"Then programmers came up with an interesting solution: each function would return the status of its work. 0 meant that it worked as expected. Any other value would mean that some error occurred, and the return value was an error code."

"However, that approach also has its shortcomings. After every (!) function call, you have to check the return code (number). First of all, this is inconvenient: the error-handling code is rarely executed but needs to be included everywhere. Second, functions often return different values – what are you supposed to do with them?"

"Right. I thought about that too."

"Then, a bright future arrived in the form of exceptions and an error-handling mechanism. Here's how it works:

1. When an error occurs, the Java Machine creates a special object – an exception – where it saves all the error information. There are different exceptions for different errors.

2. An exception causes the program to immediately exit the current function, and the next function, and so on – until it exits the main method. Then the program terminates. Programmers may also say that the Java Machine 'unwinds the call stack'."

"But you said that the program doesn't always terminate."

"Yes, because there is a way to catch an exception. We can write special code in the right place to catch the exceptions we care about and to do something with them. This is important stuff."

"To help us do this, there is a special try-catch construct. Here's how it works:"

Example of a program that catches an exception (division by 0) and keeps on working.
public class ExceptionExample2
{
    public static void main(String[] args)
    {
        System.out.println("Program starts");

        try
        {
            System.out.println("Before calling method1");
            method1();
            System.out.println("After calling method1. This will never be shown");
        }
        catch (Exception e)
        {
           System.out.println("Exception has been caught");
        }

        System.out.println("Program is still running");
    }

    public static void method1()
    {
        int a = 100;
        int b = 0;
        System.out.println(a / b);
    }
}
Screen output:
Program starts
Before method1 calling
Exception has been caught
Program is still running

"But why won't 'After calling method1. This will never be shown' be displayed on the screen?"

"I'm glad you asked. In line 25, we divide by 0, which leads to an error – an exception. The Java Machine creates an ArithmeticException object with information about the error. The object is the exception."

"The exception occurs inside the method1 method. This causes the method to terminate immediately. It would cause the main method to terminate if not for the try-catch block."

"If an exception occurs inside a try block, it is caught in the catch block. The remainder of the code in the try block won't be executed. Instead, the catch block will begin to be executed."

"I don't get it."

"In other words, the code works like this:

1. If an exception occurs inside a try block, the code ceases to be executed where the exception occurred and the catch block starts to be executed.

2. If no exception occurs, then the try block is executed to the end, and the catch block is not executed."

"Huh?"

"Imagine that after each method call we check whether the method returned normally or was abruptly terminated as a result of an exception. If there is an exception, then we move to execute the catch block (if there is one) to catch the exception. If there is no catch block, then we terminate the current method, and the method that called us performs the same check."

"I think I've got it now."

"Excellent."

"What does 'Exception' mean inside the catch statement?"

"All exceptions are classes that inherit the Exception class. We can catch a particular exception by specifying the exception class in the catch block, or we can catch all exceptions by specifying their common parent class – Exception. Then we can get all the necessary error information from the variable e (it stores a reference to the exception object)."

"Cool! If different exceptions occur in my method, then can I process them differently?"

"Not only can you, but you should. You can do that like this:"

Example:
public class ExceptionExample2
{
    public static void main(String[] args)
    {
        System.out.println("Program starts");

        try
        {
            System.out.println("Before calling method1");
            method1();
            System.out.println("After calling method1. This will never be shown");
        }
        catch (NullPointerException e)
        {
           System.out.println("Null reference. Exception has been caught");
        }
        catch (ArithmeticException e)
        {
            System.out.println("Division by zero. Exception has been caught");
        }
        catch (Exception e)
        {
            System.out.println("Any other errors. Exception has been caught");
        }

        System.out.println("Program is still running");
    }

    public static void method1()
    {
        int a = 100;
        int b = 0;
        System.out.println(a / b);
    }
}

"The try block can be paired with several catch blocks, each of which will catch the specified types of exceptions."

"I think I understand. I can't write this myself yet, but if I come across it in code, I won't get scared."