Exceptions
Exceptions
Exceptions
Disciplina: Programação Orientada a Objeto
Professor: Dr. Camilo Barreto
Curso: Grande Área de Computação
UNIUBE
1. Introdução
Em Java, uma exceção, ou exception, representa uma situação anormal que ocorre durante a execução
de um programa. Essa situação interrompe o fluxo normal das instruções e precisa ser tratada de alguma
forma para que o sistema não seja encerrado de maneira inesperada ou produza comportamentos
incorretos.
Em um programa simples, é comum imaginar que todas as entradas do usuário serão válidas, que todos
os arquivos existirão, que todos os cálculos serão possíveis e que todos os objetos estarão corretamente
inicializados. Porém, na prática, os sistemas estão sujeitos a falhas, dados inválidos e situações
inesperadas. Um usuário pode digitar texto no lugar de um número, um arquivo pode não existir, uma
conexão com banco de dados pode falhar, um objeto pode estar nulo ou uma regra de negócio pode
impedir uma operação.
As exceções existem para permitir que o programador lide com esses problemas de forma organizada.
Em vez de deixar o programa simplesmente parar, Java permite detectar a situação de erro, capturar a
exceção, executar uma ação alternativa e, quando possível, continuar a execução do sistema.
De forma resumida, uma exceção responde à seguinte pergunta:
O que o programa deve fazer quando algo inesperado acontece durante a execução?
Por exemplo:
se o usuário digitar uma idade inválida, o sistema pode solicitar a digitação novamente;
se uma divisão por zero for tentada, o sistema pode exibir uma mensagem de erro;
Exceptions 1
se um arquivo não for encontrado, o sistema pode informar o usuário e cancelar apenas aquela
operação;
se uma conta bancária não tiver saldo suficiente, o sistema pode impedir o saque e explicar o motivo;
se uma conexão com banco de dados falhar, o sistema pode registrar o problema e tentar novamente
depois.
import [Link];
Exceptions 2
[Link]("Resultado: " + resultado);
[Link]();
}
}
Esse código funciona corretamente se o usuário informar, por exemplo, os valores 10 e 2 . Nesse caso, o
resultado será 5 .
No entanto, se o usuário informar 10 e 0 , ocorrerá uma exceção, pois não é possível realizar divisão
inteira por zero em Java. O programa será interrompido e exibirá uma mensagem parecida com esta:
Essa mensagem indica que ocorreu uma exceção do tipo ArithmeticException . O problema não está na
sintaxe do código, mas em uma situação inválida durante a execução.
try {
// Código que pode gerar uma exceção.
} catch (TipoDaExcecao nomeDaExcecao) {
// Código executado quando a exceção acontece.
}
import [Link];
try {
int resultado = numero1 / numero2;
[Link]("Resultado: " + resultado);
} catch (ArithmeticException exception) {
[Link]("Erro: não é possível dividir por zero.");
}
Exceptions 3
[Link]();
}
}
Nesse exemplo, a divisão é colocada dentro do bloco try , pois é a operação que pode gerar uma
exceção. Caso numero2 seja igual a zero, Java lança uma ArithmeticException , e o bloco catch
correspondente é executado.
Com isso, o programa não termina de forma abrupta. Ele exibe uma mensagem mais compreensível para
o usuário.
int resultado = 10 / 0;
A linha que contém 10 / 0 gera uma exceção. A partir desse ponto, o restante do bloco try não é
executado. O controle do programa passa para o bloco catch . Depois que o catch termina, o programa
continua normalmente após a estrutura de tratamento.
Esse comportamento é importante porque mostra que o try/catch não corrige automaticamente o erro. Ele
apenas permite que o programador defina uma resposta adequada para aquela situação.
Exceptions 4
} catch (ArithmeticException exception) {
[Link]("Tipo de erro: " + [Link]().getSimple
Name());
[Link]("Mensagem original: " + [Link]());
}
}
}
import [Link];
try {
[Link]("Digite um número inteiro: ");
int numero = [Link]([Link]());
[Link]();
}
}
Nesse exemplo, podem acontecer pelo menos duas exceções diferentes. Se o usuário digitar um texto
como abc , a conversão para inteiro falhará e será lançada uma NumberFormatException . Se o usuário digitar
0 , a conversão funcionará, mas a divisão por zero lançará uma ArithmeticException .
A ordem dos blocos catch deve ir do tipo mais específico para o tipo mais genérico. Isso evita que uma
exceção genérica capture o erro antes que uma exceção mais específica tenha a chance de tratá-lo.
Exceptions 5
8. O bloco finally
O bloco finally é utilizado para executar um trecho de código independentemente de uma exceção
acontecer ou não. Ele é muito usado para liberar recursos, fechar arquivos, encerrar conexões ou finalizar
objetos que precisam ser encerrados corretamente.
A estrutura é:
try {
// Código que pode gerar uma exceção.
} catch (TipoDaExcecao exception) {
// Tratamento da exceção.
} finally {
// Código executado sempre.
}
Exemplo:
Mesmo que a exceção aconteça, o bloco finally será executado. Se a exceção não acontecer, ele
também será executado.
No contexto de entrada de dados, por exemplo, o finally pode ser usado para fechar o Scanner . Porém,
em programas simples executados no console, é comum fechar o Scanner apenas ao final do método
main .
import [Link];
import [Link];
import [Link];
Exceptions 6
try {
BufferedReader leitor = new BufferedReader(new FileReader("[Link]
t"));
[Link]();
} catch (IOException exception) {
[Link]("Erro ao ler o arquivo: " + [Link]
());
}
}
}
Nesse exemplo, operações de leitura de arquivo podem lançar IOException . Como essa exceção é
verificada, o Java exige que ela seja tratada com try/catch ou declarada no método com throws .
As unchecked exceptions, ou exceções não verificadas, são exceções que ocorrem em tempo de
execução e não precisam obrigatoriamente ser tratadas pelo compilador. Elas normalmente indicam
problemas de lógica, validação ou uso incorreto de objetos.
Exemplo de unchecked exception:
[Link]([Link]());
}
}
Nesse caso, ocorre uma NullPointerException , pois o código tenta chamar o método length() em uma
variável que não aponta para nenhum objeto.
if (idade < 0) {
throw new IllegalArgumentException("A idade não pode ser negativ
a.");
}
Exceptions 7
}
}
Nesse exemplo, a idade negativa não faz sentido para o sistema. Por isso, o programador lança uma
exceção do tipo IllegalArgumentException .
A palavra throws , por outro lado, é utilizada na assinatura de um método para informar que aquele método
pode lançar uma exceção. Assim, quem chamar esse método deverá tratar ou repassar a exceção.
Exemplo:
import [Link];
import [Link];
import [Link];
Nesse exemplo, o método lerPrimeiraLinha declara throws IOException . Isso indica que o método pode lançar
uma exceção de entrada e saída. O método main , ao chamar lerPrimeiraLinha , precisa lidar com essa
possibilidade.
De forma resumida:
throw : lança uma exceção;
throws : declara que um método pode lançar uma exceção.
Exceptions 8
public class SaldoInsuficienteException extends Exception {
public SaldoInsuficienteException(String mensagem) {
super(mensagem);
}
}
Nesse exemplo, a classe SaldoInsuficienteException herda de Exception . Como ela herda diretamente de
Exception , ela será uma checked exception. Isso significa que o método que puder lançá-la deverá
declarar throws SaldoInsuficienteException , e quem chamar esse método deverá tratar a exceção.
saldo += valor;
}
Exceptions 9
}
saldo -= valor;
}
}
Nesse código, o método depositar lança uma IllegalArgumentException quando o valor informado é inválido.
Essa exceção é uma unchecked exception, pois representa o uso incorreto do método.
O método sacar , além de validar o valor, também verifica se existe saldo suficiente. Caso o saldo não seja
suficiente, ele lança uma SaldoInsuficienteException , que foi criada para representar uma regra específica
do sistema bancário.
Observe que a validação das regras fica dentro da própria classe ContaBancaria . Isso é importante em
Programação Orientada a Objetos, pois a classe deve proteger seus próprios dados e garantir que seus
objetos permaneçam em um estado válido.
import [Link];
try {
[Link]("Digite o valor do saque: ");
double valorSaque = [Link]();
[Link](valorSaque);
[Link]();
Exceptions 10
}
}
Nesse exemplo, a classe ProgramaPrincipal não precisa conhecer todos os detalhes internos da conta. Ela
apenas chama o método sacar e trata as exceções que podem acontecer.
Essa separação é importante. A classe ContaBancaria concentra as regras do objeto, enquanto a classe
principal decide como apresentar o resultado ao usuário.
[Link] = nome;
}
[Link] = nota;
}
}
Exceptions 11
Nesse exemplo, o construtor utiliza os métodos setNome e setNota para aproveitar as validações. Se o
nome for nulo, vazio ou se a nota estiver fora do intervalo permitido, uma exceção será lançada.
Esse tipo de validação é comum em classes bem projetadas. O objetivo é impedir que o objeto exista com
dados inconsistentes.
[Link] = preco;
}
Nesse exemplo, a exceção impede que o atributo preco receba um valor inválido. Assim, a classe protege
seu próprio estado interno.
Portanto, exceções não devem ser vistas apenas como uma forma de lidar com erros inesperados. Elas
também podem ser utilizadas como parte do projeto da classe, ajudando a garantir regras e restrições
importantes do domínio do problema.
import [Link];
import [Link];
try {
[Link]("Digite sua idade: ");
int idade = [Link]();
if (idade < 0) {
throw new IllegalArgumentException("A idade não pode ser negativ
a.");
Exceptions 12
}
[Link]();
}
}
Nesse caso, existem dois tipos de problema. O primeiro ocorre quando o usuário digita algo que não é
inteiro. O segundo ocorre quando o usuário até digita um inteiro, mas esse inteiro não é válido para o
contexto do programa.
17. Try-with-resources
O try-with-resources é uma forma especial de try utilizada para trabalhar com recursos que precisam ser
fechados automaticamente, como arquivos, leitores, conexões e fluxos de dados.
A vantagem dessa estrutura é que o recurso declarado dentro dos parênteses do try será fechado
automaticamente ao final da execução, mesmo que uma exceção aconteça.
Exemplo:
import [Link];
import [Link];
import [Link];
Nesse exemplo, não foi necessário chamar [Link]() manualmente. O próprio Java fecha o recurso
automaticamente ao final do bloco try .
Essa abordagem é considerada uma boa prática quando se trabalha com recursos que implementam a
interface AutoCloseable .
Exceptions 13
O uso de exceções deve ser feito com cuidado. Elas são muito úteis, mas podem deixar o código confuso
se forem usadas sem critério.
Uma boa prática é tratar exceções específicas sempre que possível. Em vez de capturar Exception de
forma genérica, prefira capturar o tipo exato da exceção esperada, como NumberFormatException , IOException
ou SaldoInsuficienteException .
Exemplo menos adequado:
try {
int resultado = 10 / 0;
} catch (Exception exception) {
[Link]("Ocorreu um erro.");
}
try {
int resultado = 10 / 0;
} catch (ArithmeticException exception) {
[Link]("Não é possível dividir por zero.");
}
Também é importante não esconder erros. Um bloco catch vazio dificulta a identificação de problemas e
pode fazer o programa continuar em um estado inconsistente.
Exemplo inadequado:
try {
int resultado = 10 / 0;
} catch (ArithmeticException exception) {
Nesse exemplo, a exceção acontece, mas nada é feito. O erro é ignorado, o que prejudica a manutenção
do sistema.
Outra boa prática é apresentar mensagens claras para o usuário, sem expor detalhes técnicos
desnecessários. A mensagem para o usuário deve explicar o problema de forma simples. Já os detalhes
técnicos podem ser registrados em logs para análise posterior.
Exceptions 14
um valor recebido por parâmetro é inválido;
uma conversão de dados não pode ser realizada.
Porém, exceções não devem ser usadas como substitutas de estruturas condicionais comuns. Se uma
situação é esperada e faz parte do fluxo normal do sistema, muitas vezes um if é mais adequado.
Exemplo adequado com if :
Nesse caso, ser maior ou menor de idade não é uma situação excepcional. É apenas uma regra normal do
sistema.
Já no exemplo abaixo, lançar uma exceção pode fazer sentido, pois uma idade negativa representa um
dado inválido:
if (idade < 0) {
throw new IllegalArgumentException("A idade não pode ser negativa.");
}
[Link] = nome;
}
Exceptions 15
public double getPreco() {
return preco;
}
[Link] = preco;
}
[Link] = quantidade;
}
Classe principal:
Exceptions 16
Se os dados forem válidos, o produto será criado normalmente. Se algum dado inválido for informado, a
classe Produto lançará uma exceção e impedirá a criação de um objeto inconsistente.
Esse exemplo reforça um princípio importante da Programação Orientada a Objetos: o objeto deve ser
responsável por manter a validade de seus próprios dados.
programa, facilita a manutenção do código e contribui para a criação de sistemas mais confiáveis.
Exceptions 17