Uma exceção ou exception, é um evento ou acontecimento não desejado que pode ocorrer durante a execução de nossos programas, como erros de acesso a memória, falhas ao abrir um arquivo e outros. Quando exception acontece, um objeto contendo informações sobre a exception é lançado para que seu tratamento.

Em Java, os métodos que podem lançar exceções são declarados para serem usados dentro do bloco try. Caso isso não seja feito, o compilador exiba um erro de compilação.

Quando uma exceção acontece, precisamos obter algumas informações básicas como: mensagem do erro, onde o erro ocorreu e etc. As exceções em Java possuem os três métodos básicos abaixo.

Método Descrição
getMessage Retorna mensagem de erro
toString Retorna mensagem de erro formatada
getStackTrace Retorna pilha de execução como string
printStackTrace Imprime a pilha de execução
Exemplo 1
//Main.java
public class Main
{
	public static void main(String[] args) {
        try{
            int a = 10/0;
        }
        catch(ArithmeticException e ){
            System.out.println(e.getMessage());
            System.out.println("---------------------------------");
            System.out.println(e.toString()); //formato: {tipo_excecao}: {mensagem_erro}
            System.out.println("---------------------------------");
            e.printStackTrace();
        }
	}
}
Saída
/ by zero
---------------------------------
java.lang.ArithmeticException: / by zero
---------------------------------
java.lang.ArithmeticException: / by zero
        at Main.main(Main.java:6)

Para lançarmos uma exceção explicitamente em nossos programas em Java, utilizamos o comando throw seguindo de uma instância da exceção que desejamos lançar.

Sintaxe
throw new classe_excecao(mensagem_erro)
Onde
mensagem_erro: mensagem de erro customizada para informação
Exemplo 2
//Main.java
public class Main
{
	public static void main(String[] args) {
        try{
            throw new ArithmeticException("Um erro aritmético qualquer!");
        }
        catch(ArithmeticException e ){
            System.out.println(e.getMessage());
        }
	}
}
Saída
Um erro aritmético qualquer!

O StackTrace armazena todas as chamadas feitas aos métodos em nossos programas, até a linha em que uma exceção foi lançada. Por ser, uma Stack(pilha) a sua leitura é feita na ordem inversa.

Exemplo 3
//Main.java
public class Main
{
    public static void metodo1(){
        metodo2();
    }
    public static void metodo2(){
        metodo3();
    }
    public static void metodo3(){
         int a = 10/0;
    }
	public static void main(String[] args) {

        try{
           metodo1();
        }
        catch(ArithmeticException e ){
            e.printStackTrace();
        }
	}
}
Saída
java.lang.ArithmeticException: / by zero
        at Main.metodo3(Main.java:11)
        at Main.metodo2(Main.java:8)
        at Main.metodo1(Main.java:4)
        at Main.main(Main.java:18)

Nos exemplos acima, o bloco catch realiza algum tipo de tratamento de acordo com as exceções lançadas. Caso o tratamento possa ser feito de forma genérica, utilizamos a exceção Exception que é a classe super de todas as exeções.

Sintaxe
catch( Exception nome_objeto)
{
  //tratamento
}
            
Exemplo 4
//Main.java
public class Main
{
	public static void main(String[] args) {
        try{
            throw new ArithmeticException("Um erro aritmético qualquer!");
        }
        catch(Exception e ){
            //tratamento genérico
            System.out.println(e.getMessage());
        }
	}
}
Saída
Um erro aritmético qualquer!

No exemplo 2, utilizamos o comando throw para lançar uma exceção explicitamente. Em algumas situações, o tratamento da exceção não pode em um catch. Nesse caso, podemos relançar uma exceção para um escopo acima, utilizado o mesmo comando throw.

Sintaxe
//try omitido
catch(classe_excecao nome_objeto) 
{
    throw nome_objeto; //relançando exceção
}
Exemplo 5
//Main.java
public class Main
{
    public static void metodo(){

        try{
            int a = 1/0;
        }
        catch(Exception e){
            throw e; //relançando exceção
        }
    }
	public static void main(String[] args) {

        try{
            metodo();
        }
        catch(ArithmeticException e ){
            //recuperar mensagem da exceção
            System.out.println("exceção em main:" + e.getMessage());
        }
	}
}
Saída
exceção em metodo:/ by zero
exceção em main:/ by zero

Caso uma nova exceção seja lançada ou invés de relançada, as informações do stacktrace referentes ao erro anterior serão perdidos, "mascarando" o erro.

A linguagem Java permite que informemos que um métodos, durante sua declaração, podem lançar exceções durante sua execução. Para isso, precisamos utilizar a palavra reservada throws como na sintaxe abaixo

Sintaxe
modificador_acesso tipo_retorno nome_metodo(parametros) throws nome_excecao1, nome_excecao2, nome_excecaoN {
//corpo
}
Exemplo 6
public void meuMetodo() throws ArithmeticException{
      throw new ArithmeticException("Mensagem de erro"); 
} 
Saída
-

Um dos benefícios da utilização do throws é a verificação, em tempo de compilação, se o método está declarado dentro do corpo de um bloco try/catch ou não. Caso não esteja, um erro de compilação será exibido.

Exemplo 7 : Sem try-catch
//Main.java
public class Main
{
    public static void metodo() throws ArithmeticException {
            throw new ArithmeticException("Mensagem erro"); 
    }

	public static void main(String[] args) {
        		metodo(); //compilador verifica se está dentro de try/catch
	}
}
Saída
Main.java:8: error: unreported exception ArithmeticException; must be caught or declared to be thrown
        metodo();
              ^
1 error
Exemplo 8: Com try-catch
//Main.java
public class Main
{
    public static void metodo() throws ArithmeticException{
        throw new ArithmeticException("Mensagem erro"); 
    }
	public static void main(String[] args) {

        try{
           metodo();
        }
        catch( ArithmeticException e ){
            System.out.println(e.getMessage());
        }
	}
}
Saída
Mensagem erro
  1. 08/02/2024 - revisão 1 - correção em navegação e erros gramaticais
  2. 04/09/2023 - versão inicial