Java: Tratamento de Exceções

O tratamento de exceções torna os programas mais robustos. Esta lição cobre o mecanismo de tratamento de exceções do Java.

1. O que é uma Exceção

Uma exceção é um erro que ocorre durante a execução do programa.

(1) Classificação de Exceções

TEXT 📖 Somente leitura
Throwable
├── Error (erros graves, programa não pode tratar)
│   ├── OutOfMemoryError
│   └── StackOverflowError
└── Exception (exceções, programa pode tratar)
    ├── Exceções verificadas (devem ser tratadas)
    │   ├── IOException
    │   └── SQLException
    └── Exceções não verificadas (RuntimeException)
        ├── NullPointerException
        ├── ArrayIndexOutOfBoundsException
        └── NumberFormatException

2. try-catch

(1) Sintaxe

TEXT 📖 Somente leitura
try {
    // Código que pode lançar uma exceção
} catch (TipoExceção nomeVariável) {
    // Tratar a exceção
}

▶ Exemplo: Tratamento Básico de Exceções

JAVA
public class TryCatchDemo {
    public static void main(String[] args) {
        try {
            int result = 10 / 0;
            System.out.println(result);
        } catch (ArithmeticException e) {
            System.out.println("Erro aritmético: " + e.getMessage());
        }
        System.out.println("O programa continua");
    }
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
Erro aritmético: / by zero
O programa continua

(2) Múltiplos Blocos catch

TEXT 📖 Somente leitura
try {
    // Código que pode lançar múltiplas exceções
} catch (TipoExceção1 e1) {
    // Tratar exceção 1
} catch (TipoExceção2 e2) {
    // Tratar exceção 2
} catch (Exception e) {
    // Tratar outras exceções
}

▶ Exemplo: Múltiplos catch

JAVA
public class MultiCatch {
    public static void main(String[] args) {
        try {
            String s = "abc";
            int num = Integer.parseInt(s);
            int result = 10 / num;
        } catch (NumberFormatException e) {
            System.out.println("Erro de formato numérico: " + e.getMessage());
        } catch (ArithmeticException e) {
            System.out.println("Erro aritmético: " + e.getMessage());
        } catch (Exception e) {
            System.out.println("Outro erro: " + e.getMessage());
        }
    }
}
▶ Experimente

3. try-catch-finally

O bloco finally sempre é executado, ocorra uma exceção ou não.

(1) Sintaxe

TEXT 📖 Somente leitura
try {
    // Código que pode lançar uma exceção
} catch (TipoExceção e) {
    // Tratar a exceção
} finally {
    // Sempre executado
}

▶ Exemplo: finally

JAVA
public class FinallyDemo {
    public static void main(String[] args) {
        try {
            System.out.println("bloco try");
            int result = 10 / 0;
        } catch (ArithmeticException e) {
            System.out.println("bloco catch");
        } finally {
            System.out.println("bloco finally");
        }
    }
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
bloco try
bloco catch
bloco finally

▶ Exemplo: Liberação de Recursos

JAVA
import java.io.*;

public class ResourceDemo {
    public static void main(String[] args) {
        FileReader reader = null;
        try {
            reader = new FileReader("test.txt");
            // Ler arquivo
        } catch (FileNotFoundException e) {
            System.out.println("Arquivo não encontrado");
        } finally {
            // Liberar recurso
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
▶ Experimente

4. try-with-resources

Introduzido no Java 7, fecha recursos automaticamente.

(1) Sintaxe

JAVA
try (TipoRecurso variável = new Recurso()) {
    // Usar recurso
} catch (TipoExceção e) {
    // Tratar exceção
}

▶ Exemplo: try-with-resources

JAVA
import java.io.*;

public class TryWithResources {
    public static void main(String[] args) {
        // Fecha recurso automaticamente
        try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
            String line = reader.readLine();
            System.out.println(line);
        } catch (IOException e) {
            System.out.println("Erro de leitura: " + e.getMessage());
        }
        // reader fecha automaticamente, não precisa de finally
    }
}
▶ Experimente

5. throw e throws

(1) throw: Lançar uma Exceção

JAVA
public static int divide(int a, int b) {
    if (b == 0) {
        throw new ArithmeticException("Não é possível dividir por zero");
    }
    return a / b;
}

(2) throws: Declarar uma Exceção

TEXT 📖 Somente leitura
public static void readFile(String path) throws FileNotFoundException {
    FileReader reader = new FileReader(path);
}

▶ Exemplo: throw e throws

JAVA
public class ThrowDemo {
    public static int divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("Não é possível dividir por zero");
        }
        return a / b;
    }
    
    public static void validateAge(int age) {
        if (age < 0 || age > 150) {
            throw new IllegalArgumentException("Idade inválida: " + age);
        }
    }
    
    public static void main(String[] args) {
        try {
            System.out.println(divide(10, 0));
        } catch (ArithmeticException e) {
            System.out.println(e.getMessage());  // Não é possível dividir por zero
        }
        
        try {
            validateAge(-5);
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());  // Idade inválida: -5
        }
    }
}
▶ Experimente

6. Exceções Personalizadas

(1) Passos

  1. Estender Exception ou RuntimeException
  2. Fornecer construtores

▶ Exemplo: Exceção Personalizada

JAVA
// Classe de exceção personalizada
public class InsufficientBalanceException extends Exception {
    private double balance;
    private double amount;
    
    public InsufficientBalanceException(double balance, double amount) {
        super("Saldo insuficiente: " + balance + ", saque: " + amount);
        this.balance = balance;
        this.amount = amount;
    }
    
    public double getBalance() {
        return balance;
    }
    
    public double getAmount() {
        return amount;
    }
}

// Usando exceção personalizada
public class BankAccount {
    private double balance;
    
    public BankAccount(double balance) {
        this.balance = balance;
    }
    
    public void withdraw(double amount) throws InsufficientBalanceException {
        if (amount > balance) {
            throw new InsufficientBalanceException(balance, amount);
        }
        balance -= amount;
        System.out.println("Saque bem-sucedido, saldo: " + balance);
    }
    
    public static void main(String[] args) {
        BankAccount account = new BankAccount(1000);
        
        try {
            account.withdraw(500);   // Saque bem-sucedido, saldo: 500.0
            account.withdraw(800);   // Lança exceção
        } catch (InsufficientBalanceException e) {
            System.out.println(e.getMessage());
            System.out.println("Saldo: " + e.getBalance());
            System.out.println("Saque: " + e.getAmount());
        }
    }
}
▶ Experimente

7. Exceções Comuns

Exceção Descrição Causa
NullPointerException Ponteiro nulo Chamar método em objeto nulo
ArrayIndexOutOfBoundsException Índice de array fora dos limites Acessar índice inexistente
NumberFormatException Erro de formato numérico Conversão de string para número falhou
ClassCastException Erro de conversão de tipo Tipo de downcast incompatível
ArithmeticException Erro aritmético Dividir por zero
FileNotFoundException Arquivo não encontrado Caminho de arquivo incorreto
IOException Erro de IO Falha na leitura/escrita de arquivo

8. Princípios de Tratamento de Exceções

Princípio Descrição
Exceções específicas primeiro Capture exceções específicas antes das gerais
Não ignore exceções Pelo menos registre em log
Use finally para recursos Ou use try-with-resources
Não use exceções para controle de fluxo Exceções são para erros, não para controle de fluxo

❓ Perguntas Frequentes

P: Qual é a diferença entre Error e Exception? R: Error é um problema grave que o programa não pode tratar. Exception é um problema que o programa pode capturar e tratar.

P: Qual é a diferença entre exceções verificadas e não verificadas? R: Exceções verificadas devem ser tratadas (try-catch ou throws). Exceções não verificadas não precisam ser tratadas.

P: Quando devo criar exceções personalizadas? R: Quando precisar distinguir tipos de exceções de negócios, como saldo insuficiente ou usuário não encontrado.

📖 Resumo

📝 Exercícios

  1. Tratamento de exceções: Escreva um método para ler um arquivo, tratando arquivo não encontrado e erros de leitura
  2. Exceção personalizada: Defina uma exceção AgeOutOfBoundsException para validação de idade
  3. Gerenciamento de recursos: Use try-with-resources para implementar cópia de arquivo

9. Próxima Lição

Na próxima lição, aprenderemos sobre Prática: OOP — aplicando conhecimentos de orientação a objetos.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%