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.

O que é uma Exceção

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

Classificação de Exceções

TEXT
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

try-catch

Sintaxe

JAVA
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
Erro aritmético: / by zero
O programa continua

Múltiplos Blocos catch

JAVA
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

try-catch-finally

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

Sintaxe

JAVA
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
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

try-with-resources

Introduzido no Java 7, fecha recursos automaticamente.

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

throw e throws

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;
}

throws: Declarar uma Exceção

JAVA
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

Exceções Personalizadas

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

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

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

Próxima Lição

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

100%