CodeGym /Cursos /JAVA 25 SELF /Propagação de exceções (throws)

Propagação de exceções (throws)

JAVA 25 SELF
Nível 11, Lição 4
Disponível

1. Introdução

No desenvolvimento de software, muitas vezes há situações em que um método se depara com um erro, mas não sabe como tratá‑lo corretamente. Por exemplo, o método lê um arquivo, mas não sabe o que fazer se o arquivo não existir: perguntar ao usuário? Encerrar o programa? Tentar outro arquivo? Nesses casos, o método pode “transferir a responsabilidade” para quem o chamou — ou seja, “propagar” a exceção adiante na cadeia de chamadas.

Propagação de exceção é um mecanismo que permite ao método não tratar o erro por conta própria, mas informar ao código chamador: “Tenho um problema aqui, resolva você!”

Analogia: imagine que você é um atendente de call center. Um cliente liga com uma pergunta para a qual você não tem a resposta. Em vez de adivinhar, você diz: “Um instante, vou transferi-lo para um especialista”. Você “propaga” a questão adiante.

Palavra-chave throws: como funciona

Em Java, para propagar exceções usa‑se a palavra‑chave throws na declaração do método.

Sintaxe:

tip_vozvrashchaemogo_znacheniya imyaMetoda(...) throws ExceptionType 
{
    // código do método
}

Após throws, especifica‑se o tipo de exceção que pode ocorrer neste método. É como um aviso para outros desenvolvedores: “Atenção! Este método pode lançar uma exceção deste tipo. Esteja preparado!”

Exemplo:

public void readFile(String filename) throws FileNotFoundException 
{
    FileReader reader = new FileReader(filename); // pode lançar FileNotFoundException
    // ...
}

Aqui, o método readFile não trata o erro por conta própria; ele informa: “Posso lançar FileNotFoundException — que o chamador decida o que fazer”.

2. Como o método chamador deve reagir?

Se você chama um método que foi declarado com throws, você tem duas opções:

  • Tratar a exceção com try-catch
  • Também propagar a exceção adiante (adicionar throws no seu método)

Opção 1: tratar com try-catch

public static void main(String[] args) 
{
    try 
    {
        readFile("data.txt");
    } 
    catch (FileNotFoundException e) 
    {
        System.out.println("Arquivo não encontrado: " + e.getMessage());
    }
}

Aqui capturamos a exceção e decidimos o que fazer (por exemplo, exibimos uma mensagem para o usuário).

Opção 2: propagar adiante

public static void main(String[] args) throws FileNotFoundException 
{
    readFile("data.txt");
}

Agora a responsabilidade pelo tratamento do erro recai sobre quem chamar main (normalmente a própria JVM — se o erro não for tratado, o programa será encerrado com uma mensagem de erro).

3. Exemplo: leitura de arquivo com propagação de exceção

Exemplo completo com IOException e tratamento no nível de main:

import java.io.*;

public class FileDemo 
{
    // O método declara que pode lançar IOException
    public static void printFirstLine(String filename) throws IOException 
    {
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        String line = reader.readLine();
        System.out.println("Primeira linha: " + line);
        reader.close();
    }

    public static void main(String[] args) 
    {
        try 
        {
            printFirstLine("nofile.txt");
        } 
        catch (IOException e) 
        {
            System.out.println("Erro ao ler o arquivo: " + e.getMessage());
        }
    }
}

O método printFirstLine não sabe o que fazer se o arquivo não existir — ele apenas propaga a exceção. Em main nós capturamos o erro e exibimos a mensagem.

4. Nuances úteis

Quando e por que usar a propagação de exceções?

  • Quando o método não pode ou não deve decidir como tratar o erro (por exemplo, código de biblioteca).
  • Quando o tratamento do erro depende do contexto (em um caso encerrar o programa, em outro — tentar outro arquivo).
  • Para não poluir o código com try-catch desnecessários onde isso não é preciso.

Boas práticas: Propage exceções se você não puder tratá‑las de forma significativa. Não capture exceções apenas “por obrigação”!

É possível propagar várias exceções

public void process() throws IOException, SQLException 
{
    // ...
}

Exceções verificadas (checked) e não verificadas (unchecked): lembrete

Exceções verificadas (checked) (por exemplo, IOException, SQLException) — o compilador exige que sejam tratadas ou propagadas.

Exceções não verificadas (unchecked) (por exemplo, NullPointerException, IllegalArgumentException) — o compilador não exige tratamento; não é necessário declará‑las em throws.

5. Erros comuns ao propagar exceções

Erro nº 1: esqueceu de declarar throws para uma exceção verificada (checked).
Se um método pode lançar uma exceção verificada e você não a declarou em throws nem a tratou com try-catch, o compilador emitirá um erro.

Erro nº 2: você captura a exceção, mas não a trata.
Escrever catch (Exception e) {} é má prática! É melhor propagar a exceção adiante se você não sabe o que fazer com ela.

Erro nº 3: você propaga um tipo genérico demais.
Se o método só pode lançar FileNotFoundException, não escreva throws Exception — isso dificulta o entendimento do código.

Erro nº 4: você lista exceções não verificadas (unchecked) em throws.
Não faz sentido escrever throws NullPointerException — o compilador não exige isso e não ajuda no tratamento de erros.

1
Tarefa
JAVA 25 SELF, nível 11, lição 4
Bloqueado
Módulo de acesso a documentos secretos 📁
Módulo de acesso a documentos secretos 📁
1
Tarefa
JAVA 25 SELF, nível 11, lição 4
Bloqueado
Ferramenta de análise de logs: tratamento de falhas de leitura 📊
Ferramenta de análise de logs: tratamento de falhas de leitura 📊
1
Tarefa
JAVA 25 SELF, nível 11, lição 4
Bloqueado
Pipeline de processamento de dados: problemas esperados com o arquivo ⚙️
Pipeline de processamento de dados: problemas esperados com o arquivo ⚙️
1
Tarefa
JAVA 25 SELF, nível 11, lição 4
Bloqueado
Corrida do Ouro: conversão da entrada do jogador 💰
Corrida do Ouro: conversão da entrada do jogador 💰
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION