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.
GO TO FULL VERSION