"Oi, amigo. Hoje vamos ter uma aula muito interessante. Vou falar sobre exceções. Exceções são um mecanismo especial que nos permite tratar erros no programa. Aqui estão alguns exemplos de erros que podem ocorrer em um programa:

1. O programa pode tentar gravar um arquivo quando o disco rígido estiver completamente cheio.

2. O programa pode tentar chamar um método em uma variável que armazena uma referência nula.

3. O programa pode tentar dividir um número por 0."

Todas essas ações resultam em erros. Normalmente, o resultado é que o programa termina imediatamente, pois não faz sentido continuar executando o código nesse caso.

"Por que?"

"Faz sentido continuar virando o volante se o carro saiu da estrada e caiu de um penhasco?"

"O programa deveria parar de rodar, então?"

"Sim. Pelo menos, isso é o que costumava acontecer. Qualquer erro causava o encerramento do programa."

"Essa é uma abordagem muito inteligente."

"Mas não seria melhor tentar continuar rodando o programa?"

"Sim. Suponha que você digitou uma grande quantidade de texto no Word e o salvou. E se a operação de salvamento falhar, mas o programa o levar a acreditar que está tudo bem? E você continua digitando. Isso seria estúpido, não seria? isto?"

"Sim."

"Então os programadores encontraram uma solução interessante: cada função retornaria o status de seu trabalho. 0 significava que funcionava conforme o esperado. Qualquer outro valor significaria que algum erro ocorreu e o valor de retorno era um código de erro."

"No entanto, essa abordagem também tem suas deficiências. Após cada (!) chamada de função, você deve verificar o código de retorno (número). Em primeiro lugar, isso é inconveniente: o código de tratamento de erros raramente é executado, mas precisa ser incluído em todos os lugares. Em segundo lugar, as funções geralmente retornam valores diferentes - o que você deve fazer com eles?"

"Certo. Eu pensei sobre isso também."

"Então, um futuro brilhante chegou na forma de exceções e um mecanismo de tratamento de erros. Veja como funciona:

1. Quando ocorre um erro, a Java Machine cria um objeto especial – uma exceção – onde salva todas as informações do erro. Existem exceções diferentes para erros diferentes.

2. Uma exceção faz com que o programa saia imediatamente da função atual, da próxima função e assim por diante – até sair do método principal. Então o programa termina. Os programadores também podem dizer que a Java Machine 'desenrola a pilha de chamadas'."

"Mas você disse que o programa nem sempre termina."

"Sim, porque existe uma maneira de capturar uma exceção. Podemos escrever um código especial no lugar certo para capturar as exceções com as quais nos preocupamos e fazer algo com elas. Isso é importante."

"Para nos ajudar a fazer isso, existe uma construção especial try-catch . Veja como funciona:"

Exemplo de programa que pega uma exceção (divisão por 0) e continua funcionando.
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);
    }
}
Saída da tela:

Program starts
Before method1 calling
Exception has been caught
Program is still running

"Mas por que 'Depois de chamar o método 1. Isso nunca será mostrado' não será exibido na tela?"

"Que bom que você perguntou. Na linha 25, dividimos por 0, o que leva a um erro – uma exceção. A Java Machine cria um objeto ArithmeticException com informações sobre o erro. O objeto é a exceção."

"A exceção ocorre dentro do method1método. Isso faz com que o método seja encerrado imediatamente. Isso faria com que o método principal fosse encerrado se não fosse pelo bloco try-catch ."

"Se ocorrer uma exceção dentro de um bloco try, ela será capturada no bloco catch . O restante do código no bloco try não será executado. Em vez disso, o bloco catch começará a ser executado. "

"Eu não entendo."

"Em outras palavras, o código funciona assim:

1. Se ocorrer uma exceção dentro de um bloco try , o código deixa de ser executado onde ocorreu a exceção e o bloco catch passa a ser executado.

2. Se nenhuma exceção ocorrer, o bloco try será executado até o final e o bloco catch não será executado. "

"Huh?"

"Imagine que, após cada chamada de método, verificamos se o método retornou normalmente ou foi encerrado abruptamente como resultado de uma exceção. Se houver uma exceção, passamos a executar o bloco catch (se houver) para capturar a exceção. Se não houver bloco catch, encerramos o método atual e o método que nos chamou executa a mesma verificação."

"Acho que entendi agora."

"Excelente."

"O que significa 'Exception' dentro da instrução catch?"

" Todas as exceções são classes que herdam a classe Exception. Podemos capturar uma exceção específica especificando a classe de exceção no bloco catch ou podemos capturar todas as exceções especificando sua classe pai comum – Exception. Então, podemos obter todos os erros necessários informações da variável e (armazena uma referência ao objeto de exceção)."

"Legal! Se diferentes exceções ocorrerem no meu método, posso processá-las de maneira diferente?"

"Não só você pode, mas você deve. Você pode fazer isso assim:"

Exemplo:
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);
    }
}

"O bloco try pode ser emparelhado com vários blocos catch , cada um dos quais irá capturar os tipos especificados de exceções."

"Acho que entendo. Ainda não posso escrever isso sozinho, mas se eu encontrar em código, não vou ficar com medo."