1. Classe Throwable: a raiz de todas as exceções
Agora vamos detalhar como o sistema de exceções no Java é estruturado: o que é Throwable, em que Exception e Error diferem e o que significam as exceções “verificadas” e “não verificadas”. Este é o fundamento para um tratamento de erros adequado nos seus programas.
No Java, todas as exceções e erros são objetos que herdam da classe java.lang.Throwable.
Throwable é o “ancestral” de toda a hierarquia de tratamento de problemas no Java.
Esquematicamente:
Throwable
├── Exception
└── Error
Throwable é a classe base de tudo o que pode ser “lançado” (throw) e “capturado” (catch) em Java. Não se usa essa classe diretamente — ela serve de base para tipos de erro mais específicos.
Exception — para erros “normais”
Exception é a classe base para todas as exceções que podem surgir no programa e que você pode e deve tratar. São erros operacionais: problemas com arquivos, rede, entrada/saída, erros do usuário etc. A maioria dos seus try-catch trabalhará justamente com subclasses de Exception.
Exemplos:
- IOException — erro ao trabalhar com arquivos ou rede.
- SQLException — erro ao trabalhar com banco de dados.
- FileNotFoundException — arquivo não encontrado.
Error — para erros fatais da JVM
Error é a classe base para erros que ocorrem no nível da máquina virtual Java (JVM). Normalmente são falhas críticas que o programa não pode e não deve tratar. Se ocorrer um Error — é bem provável que o aplicativo não consiga continuar executando.
Exemplos:
- OutOfMemoryError — a memória acabou.
- StackOverflowError — estouro de pilha (por exemplo, por recursão infinita).
- NoClassDefFoundError — a classe necessária não foi encontrada.
Importante:
Capturar e tratar Error — quase sempre é uma má ideia. Não são erros do seu programa, mas falhas do ambiente de execução.
2. Checked vs Unchecked exceptions: o que isso significa?
No Java, todas as exceções se dividem em dois grandes grupos:
Exceções verificadas (Checked)
O que são? Exceções que o compilador obriga você a tratar ou a propagar explicitamente.
Quando ocorrem? Geralmente estão ligadas a recursos externos: arquivos, rede, bancos de dados, entrada do usuário.
Como tratar? Você deve envolver o código com try-catch ou adicionar throws à assinatura do método.
Exemplos: IOException, SQLException, FileNotFoundException
Exemplo:
public void readFile(String path) throws IOException {
FileReader reader = new FileReader(path); // pode lançar IOException
// ...
}
Se você não tratar nem propagar — o programa não vai compilar!
Exceções não verificadas (Unchecked)
O que são? Exceções que não exigem tratamento obrigatório pelo compilador.
Quando ocorrem? Geralmente são erros na lógica do programa: divisão por zero, acesso fora dos limites do array, acesso a null.
Como tratar? Pode capturar, mas não é obrigatório. É melhor prevenir esses erros com verificações.
Onde na hierarquia? Todas herdam de RuntimeException.
Exemplos: NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException, ArithmeticException
Exemplo:
int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException
O compilador não exige que você capture essa exceção — mas o programa falhará quando o erro ocorrer.
3. Toda a hierarquia em uma figura
graph TD
Throwable --> Error
Throwable --> Exception
Exception --> RuntimeException
Exception --> CheckedExceptions["(outras exceções verificadas)"]
Error --> OutOfMemoryError
Error --> StackOverflowError
RuntimeException --> NullPointerException
RuntimeException --> IndexOutOfBoundsException
RuntimeException --> IllegalArgumentException
%% Estilos
style Throwable fill:#ffa64d,color:#000
style Exception fill:#ffa64d,color:#000
style CheckedExceptions fill:#ffa64d,color:#000
style Error fill:#ff4d4d,color:#fff
style OutOfMemoryError fill:#ff4d4d,color:#fff
style StackOverflowError fill:#ff4d4d,color:#fff
style RuntimeException fill:#4dff88,color:#000
style NullPointerException fill:#4dff88,color:#000
style IndexOutOfBoundsException fill:#4dff88,color:#000
style IllegalArgumentException fill:#4dff88,color:#000
Tabela: diferenças principais
| Grupo | Classe pai | Exige tratamento? | Exemplos |
|---|---|---|---|
| Checked Exception | |
Sim | |
| Unchecked | |
Não | |
| Error | |
Não | |
4. Como isso aparece no código?
Checked Exception: exemplo com arquivos
import java.io.*;
public class FileDemo {
public static void main(String[] args) {
try {
FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
int data = reader.read();
System.out.println(data);
reader.close();
} catch (IOException e) {
System.out.println("Erro ao trabalhar com arquivo: " + e.getMessage());
}
}
}
O compilador vai obrigar você a tratar IOException!
Unchecked Exception: exemplo de divisão por zero
public class ExceptionDemo {
public static void main(String[] args) {
int a = 10;
int b = 0;
int c = a / b; // ArithmeticException (unchecked)
System.out.println("Resultado: " + c);
}
}
O compilador não exige tratamento, mas o programa vai falhar.
5. Por que precisamos da hierarquia de exceções?
- Flexibilidade no tratamento: É possível capturar erros específicos (FileNotFoundException) ou grupos inteiros (IOException ou Exception).
- Reutilização de código: Permite tratar centralizadamente erros de um mesmo tipo.
- Código mais limpo: A lógica principal não fica poluída com verificações para cada detalhe.
Exemplo:
try {
// código perigoso
} catch (FileNotFoundException e) {
System.out.println("Arquivo não encontrado!");
} catch (IOException e) {
System.out.println("Erro de E/S!");
} catch (Exception e) {
System.out.println("Algo deu errado: " + e.getMessage());
}
6. Erros típicos ao trabalhar com exceções
Erro nº 1: Ignorar exceções. Escrever catch (Exception e) {} — é ruim! Você perde informações sobre a causa do erro.
Erro nº 2: Capturar demais. catch (Exception e) captura tudo, até o que você não esperava. É melhor capturar apenas as exceções que você sabe tratar.
Erro nº 3: Capturar Errors. Não capture Error a menos que você esteja escrevendo código de baixo nível. Esses são problemas da JVM, não do seu programa.
Erro nº 4: Não distinguir checked e unchecked. Nem todas as exceções são iguais! As checked exigem tratamento (Exception); as unchecked — não (RuntimeException e suas subclasses).
Erro nº 5: Não adicionar informações às exceções. Se você cria suas próprias exceções — sempre adicione uma mensagem informativa.
GO TO FULL VERSION