Você está na página 1de 22

Tratamento de Exceções

Programação Orientada a Objetos


Prof. Bernardo Copstein
Leitura recomendada
• Cay Horstmann; Java for Everyone; Capítulo 7, seção 7.4
O que são exceções
• Uma exceção indica que alguma condição ou erro excepcional
ocorreu.
• Disparar uma exceção é sinalizar uma condição excepcional.
• Capturar uma exceção é trata-la, ou seja, realizar as ações necessárias
para se recuperar dela.
• Em Java usa-se o comando throw para lançar uma exceção:
throw <expressão>
• A <expressão> deve corresponder a um objeto que represente a condição ou
erro excepcional que ocorreu
• Ex: throw new IlegalArgumentException(“x tem de ser >= 0”);
Quando lançar uma exceção
• Um método pode lançar uma exceção sempre que atingir um estado de erro que é melhor tratado
fora de seu contexto.
• Ex:
• método que calcula o fatorial de um número recebe como argumento um valor menor que zero.
• nesta situação o cálculo não tem como prosseguir, não existe tratamento possível dentro do método, lança-se
uma exceção (veja o código abaixo).

public double fatorial(int x){


if (x<0){
throw new IllegalArgumentException(“x must be >= 0”);
}else{
double fact;
for(fact = 1.0; x>1; x--){
fact = fact * x;
}
return(fact);
}
}
Como o Java reage a ocorrência de uma
exceção?
• Quando uma exceção é lançada, a JVM interrompe a execução normal do programa e passa a procurar
um “tratador” que possa capturar ou tratar a exceção.
• Note que as exceções podem ser lançadas pelo programador (comando throw) ou pelo próprio sistema
(ex: divisão por zero).
• Tratadores de exceção são escritos com os comandos try/catch/finally.
• Se o bloco de comandos ({...}) que envolve o lançamento da exceção contiver um tratador de exceção, o
tratador é executado e o programa prossegue.
• Caso contrário o tratador será procurado no bloco de comandos mais externo.
• Não sendo encontrado nenhum tratador no método corrente, a execução do método é interrompida e a
busca continua no método chamador.
• Não sendo encontrado nenhum tratador a busca continuará, desempilhando os métodos chamadores,
até chegar no método main.
• Não havendo tratador no main a execução do programa é interrompida e a mensagem correspondente
a exceção é exibida.
Exemplo de exceção sem tratamento
(lançada pelo programador)

public class Main {


public static double fatorial(int x) {
if (x < 0) {
throw new IllegalArgumentException("x must be >= 0");
} else { public static void main(String[] args) {
int continua = 0;
double fact;
Scanner sc = new Scanner(System.in);
for (fact = 1.0; x > 1; x--) { do{
fact = fact * x; System.out.print("Digite o valor para o
calculo:");
} int x = sc.nextInt();
double result = fatorial(x);
return (fact);
System.out.println("Fatorial de "+x+" = "+result);
} System.out.println("Digite 0 p/cont.");
} continua = sc.nextInt();
}while(continua == 0);
System.out.println("Fim");
}
}
Exemplo de exceção sem tratamento
(lançada pelo sistema)

public class Main {


public static double divide(int a,int b) {
double resp = a/b; // se b == 0 lança ArithmeticException
return (resp);
}

public static void main(String[] args) {


int n1 = 10;
int n2 = 0;
double result = divide(n1,n2);
System.out.println(“Resultado: “+result);
}
}
Tratando as exceções
• O comando try/catch/finally é o mecanismo de tratamento de
exceções em Java.
• O programa irá “tentar” executar o bloco de comandos associado a
cláusula try. Em caso de sucesso, o bloco é executado e o fluxo do
programa continua normalmente após a clausula catch.
• No caso de ser lançada uma exceção dentro do bloco “try” o fluxo é
desviado automaticamente para a clausula “catch” onde deve ser
feito o tratamento adequado, e depois segue normalmente.
• A clausula “finally” é executada sempre, independente de ter
ocorrido exceção ou não.
Exemplo de tratamento de exceções
(fora do método onde ocorreu)

public static void main(String[] args) {


int continua = 0; double result = 0;
Scanner sc = new Scanner(System.in);
do{
System.out.print("Digite o valor para o calculo:");
int x = sc.nextInt();
try{
result = fatorial(x);
System.out.println("Fatorial de "+x+" = "+result);
}catch(IllegalArgumentException e){
System.out.println("Valor invalido p/calculo do fatorial");
System.out.println("Tente novamente");
}
System.out.println("Digite 0 p/cont ou qq outro nro para parar"); Em caso de exceção o fluxo é
continua = sc.nextInt(); OEm
sistema
desviado
caso de
tenta
para
execução
executar
a clausula
normal
o trecho
“catch”
o fluxo
em
}while(continua == 0); segue
(trecho
depois
azul)
verde
daecláusula
depois
... segue
“catch”
System.out.println("Fim");
normalmente
}
Exemplo de tratamento de exceções
(no método onde ocorreu)

public class Main {


public static double divide(int a,int b) {
try{
double resp = a/b;
return (resp);
}catch(ArithMeticException e){
return(Double.NaN);
}
} public static void main(String[] args) {
int n1 = 10;
int n2 = 0;
... double result = divide(n1,n2);
System.out.println(“Resultado: “+result);
} }
Exemplo de tratamento de exceções
(no método onde ocorreu usando finally)

public class Main {


private static int cont = 0;

public static double divide(int a,int b) {


try{
double resp = a/b;
return (resp);
}catch(ArithMeticException e){
return(Double.NaN);
}finally{
cont++;  a contagem será feita independente da ocorrência da exceção !!
}
}
...
Tipos de exceções (1)
• Exceções em Java são modeladas por objetos
• Os diferentes tipos de exceções são criados a partir de classes derivadas da
classe Throwable.
• Essa derivação é feita por herança
• A grande maioria das exceções é derivada das classes “Error” ou
“Exception”.
• As derivadas de “Error” normalmente representam situações irrecuperáveis
• Falta de memória
• Problema de hardware
• Arquivo corrompido
Tipos de exceções (2)
• As exceções derivadas de “Exception” indicam condições menos
severas:
• Operação aritmética inválida (ArithmeticException)
• Referência nula (NullPointerException)
• Fim de arquivo (IOError)
• Indice de array inválido (IndexOutOfBoundsException)
• Argumento inválido (IllegalArgumentException)
• etc
Exceções verificadas x não verificadas
• Em Java as exceções podem ser verificadas ou não verificadas
• Exceções não verificadas são aquelas que não podemos prever com antecedência (ex:
Out of memory) e portanto não podemos prever código para seu tratamento.
• Exceções verificadas são aquelas que podemos prever a possível ocorrência e portanto o
Java exige um tratamento .
• Todos os subtipos de “Error” são não verificados
• Todos os subtipos de “Exception” são verificados. A exceção são os subtipos de
“RuntimeException” (um subtipo de “Exception”) que também não são verificados.
• Se um trecho de código lança uma exceção verificada o compilador irá acusar erro caso
o tratamento adequado não tenha sido previsto.
• Se um trecho de código lança uma exceção não verificada não há necessidade de
prever tratamento.
Hierarquia de classes de exceções
Repassando exceções
• Eventualmente um método pode lançar uma exceção verificada que não deseja prever o
tratamento.
• Neste caso o método pode repassar a exceção para o método chamador. Este por sua vez deverá
providenciar o tratamento ou repassar também.
• Um método pode repassar automaticamente uma exceção para o método chamador declarando
tal situação na definição do método.

public void f1() throws InterruptedException{


System.out.println("Espere um pouco ...");
Thread.sleep(200);
System.out.println("Obrigado");
}
Tratando várias exceções simultaneamente (1)
• Se um método pode lançar diferentes tipos de exceções ...

public static double fatorial(int x){


if (x < 0) {
throw new IllegalArgumentException("x must be >= 0");
} else if (x > 100){
throw new ArithmeticException("Valor muito grande");
}else{
double fact;
for (fact = 1.0; x > 1; x--) {
fact = fact * x;
}
return (fact);
}
}
Professores de Alpro II - FACIN/PUCRS 17
Tratando várias exceções simultaneamente (2)
• ... então podemos capturar várias exceções em um mesmo comando try/catch
try{
result = fatorial(x);
System.out.println("Fatorial de "+x+" = "+result);
}catch(IllegalArgumentException e){
System.out.println("Valor negativo inv. p/calculo do fatorial");
System.out.println("Tente novamente");
}catch(ArithmeticException e){
System.out.println("Valor muito grande p/calculo do fatorial");
System.out.println("Tente novamente");
}

• Neste caso as exceções são analisadas na ordem em que aparecem nas clausulas “catch”.
• Note que as regras de polimorfismo continuam valendo: se uma superclasse aparecer antes
de uma subclasse acabará capturando todas as exceções derivadas.
Outro exemplo com finally
• A clausula “finally” indica um trecho de código que sempre será executado, ocorrendo exceção ou não.
• Normalmente é usado para garantir que recursos que estão sendo utilizados no momento que ocorreu a
exceção sejam liberados.
try{
result = fatorial(x);
System.out.println("Fatorial de "+x+" = "+result);
}catch(IllegalArgumentException e){
System.out.println("Valor negativo invalido p/calculo do fatorial");
System.out.println("Tente novamente");
}catch(ArithmeticException e){
System.out.println("Valor muito grande para o calculo do fatorial");
System.out.println("Tente novamente");
}finally{
System.out.println("Esse trecho sempre é executado!!");
}
Criando classes para representar exceções
• É conveniente criar classes para representar exceções quando as classes
de exceção previstas na API do Java não expressam adequadamente a
situação que se deseja sinalizar.
• É uma questão de semântica e clareza ou
• Quando se deseja que a “exceção” carregue mais informações.
• Novas exceções são criadas por herança a partir das já existentes
• É importante definir se a nova exceção necessita ser verificada ou não
• Não verificadas: normalmente indicam mau uso dos métodos por parte do
programador.
• Verificadas: condições de exceção que podem ocorrer mesmo usando-se
corretamente os métodos
Exemplos
• Exceção verificada: • Exceção não verificada:
public class FooException extends Exception {
public FooException() { super(); } public class FooRuntimeException
extends RuntimeException {
public FooException(String message) {
...
super(message);
}
}
public FooException(String message, Throwable cause){
super(message, cause);
}
public FooException(Throwable cause) {
super(cause);
}
}

Você também pode gostar