Prévia do material em texto
Tratamento de Exceções
Prof. Marco Túlio de Oliveira Valente
Prof. César Francisco de Moura Couto
Prof. Pedro Felipe A. Oliveira
2
Introdução
§ Programas devem tratar erros ou situações não previstas:
§ Exemplos: divisão por zero, indexação de um vetor
além de seus limites, overflow em uma operação
aritmética, memória insuficiente, disco cheio etc
§ Problema: formas convencionais “poluem” o programa
com código para tratamento de erros
§ Chegando a 2/3 do código em alguns programas
§ Solução: exceções
3
Introdução
§ Exceção: erro ou um estado imprevisto, que não ocorre com
freqüência
§ Idéia: remover o tratamento de erros do fluxo normal de
execução, de forma a não “poluir” o código.
§ Tratador (ou Manipulador) de Exceção: bloco de código para
onde a execução é desviada quando ocorre uma exceção
§ Primeira linguagem: PL/I (1964)
§ Atualmente: ADA, C++, Java etc
§ Exceções em linguagens de programação:
§ Como ativar uma exceção ?
§ Como especificar um tratador de exceções ?
§ Como exceções são propagadas?
§ Como retornar ao fluxo normal de execução ?
4
Tratamento de Exceções em C++
§ Como ativar uma exceção em C++ ?
§ Através do comando throw <expressão>
§ Exemplo:
class DivisaoPorZero { } ;
double divisao (double x, double y) {
if (y = = 0)
throw DivisaoPorZero (); // ativa (ou levanta) exceção
return x / y;
}
§ throw: abandona execução do bloco corrente e passa a
executar um tratador de exceções
5
Tratamento de Exceções em C++
§ Como especificar um tratador de exceções em C++ ?
§ Através dos comandos:
try { ..... } // comandos que podem ativar exceções
catch (parâmetro formal) { ..... } // tratador
catch (parâmetro formal) { ..... }
§ Exceções ocorridas no interior de um try são transferidas
para o catch correspondente
§ Exemplo:
try { ......
divisao (5.0, 0.0); // ativa uma exceção
..........
}
catch (DivisaoPorZero) { // “captura” exceção
.....; cout << “divisão por zero”; .....
}
6
Tratamento de Exceções em C++
Sem Tratamento de Exceções:
ok= AbraArquivo (nome);
if (ok) {
tam= TamanhoArquivo (nome);
if (tam != 0) {
p= AloqueMemoria (tam);
if (p != NULL) {
.....
}
else { ....... }
}
else { ........ }
}
else { ....... }
Com Tratamento de Exceções :
try {
abraArquivo (nome);
tam= TamanhoArquivo (nome);
p= AloqueMemoria (tam);
......
}
catch (ExcecaoAberturaArquivo)
{ ....... }
catch (ExcecaoTamanhoArquivo)
{ ...... }
catch (ExcecaoAlocacaoMemoria)
{ ...... }
§ Exemplo:
7
Tratamento de Exceções em C++
§ Como exceções são propagadas ?
§ Exceções são propagadas automaticamente, terminando
cada um dos blocos e funções do programa, até se
encontrar um tratador com parâmetro formal do mesmo
tipo do objeto especificado na ativação da exceção.
§ Em outras palavras, procura-se na pilha de ativação de
blocos e funções, o primeiro catch que trate a exceção
ativada
§ Como um tratador é escolhido ?
catch (A) { ... } // captura exceções da classe A e das subclasses de A
catch (B) { .... } // captura exceções da classe B e das subclasses de B
catch (...) { ... } // captura exceções de qualquer classe (catch-all)
8
Tratamento de Exceções em C++
void f (int a) {
cout << "f-inicio ";
try {
divisao (5.0, a);
}
catch (Overflow) {
cout << "f-over";
}
cout << "f-fim ";
}
void g () {
int a;
cout << "g-inicio ";
try {
cin >> a; f (a);
}
catch (DivisaoPorZero) {
cout << "g-div0 ";
}
cout << "g-fim ";
}
void main () { // Resultado:
g (); // a= 1: g-inicio f-inicio f-fim g-fim
} // a= 0: g-inicio f-inicio g-div0 g-fim
Exemplo
§ Exemplo:
9
Tratamento de Exceções em C++
§ Como retornar ao fluxo normal de execução após tratar
uma exceção ?
§ Basta que encontre-se um bloco catch que trate o tipo da
exceção levantada
§ Este bloco é então executado;
§ A exceção é desativada;
§ E a execução prossegue na linha seguinte ao bloco
§ Como reativar uma exceção dentro de um bloco catch ?
§ Através do comando throw
§ Exemplo:
catch (A) { .....
throw; // reativa exceção do tipo A
.....
}
10
Tratamento de Exceções em Java
§ Exceções são
§ Erros de tempo de execução
§ Objetos criados a partir de classes especiais que são
"lançados" quando ocorrem condições excepcionais
§ Métodos podem capturar ou deixar passar exceções que
ocorrerem em seu corpo
§ É obrigatório, para a maior parte das exceções, que o
método declare quaisquer exceções que ele não capturar
§ Mecanismo try-catch é usado para tentar capturar exceções
enquanto elas passam por métodos
11
Três tipos de erros
§ Erros de lógica de programação
§ Ex: limites do vetor ultrapassados, divisão por zero
§ Devem ser corrigidos pelo programador
§ Erros devido a condições do ambiente de execução
§ Ex: arquivo não encontrado, rede fora do ar, etc.
§ Fogem do controle do programador mas podem ser
contornados em tempo de execução
§ Erros graves onde não adianta tentar recuperação
§ Ex: falta de memória, erro interno do JVM
§ Fogem do controle do programador e não podem ser
contornados
12
Como causar uma exceção?
§ Uma exceção é um tipo de objeto que sinaliza que uma
condição excepcional ocorreu
§ A identificação (nome da classe) é sua parte mais
importante
§ Precisa ser criada com new e depois lançada com throw
IllegalArgumentException e =
new IllegalArgumentException("Erro!");
throw e; // exceção foi lançada!
§ A referência é desnecessária. A sintaxe abaixo é mais usual:
throw new IllegalArgumentException("Erro!");
13
Exceções e métodos
§ Uma declaração throws (observe o "s") é obrigatória em
métodos e construtores que deixam de capturar uma ou mais
exceções que ocorrem em seu interior
public void m() throws Excecao1, Excecao2 {...}
public Circulo() throws ExcecaoDeLimite {...}
§ throws declara que o método pode provocar exceções do tipo
declarado (ou de qualquer subtipo)
§ A declaração abaixo declara que o método pode provocar
qualquer exceção (nunca faça isto)
public void m() throws Exception {...}
§ Métodos redefinidos não podem provocar mais exceções que
os métodos originais
14
Fluxo
§ Uma exceção lançada interrompe o fluxo normal do
programa
§ O fluxo do programa segue a exceção
§ Se o método onde ela ocorrer não a capturar, ela será
propagada para o método que chamar esse método e
assim por diante
§ Se ninguém capturar a exceção, ela irá causar o término
da aplicação
§ Se em algum lugar ela for capturada, o controle pode ser
recuperado
15
Captura e Declaração
public class RelatorioFinanceiro {
public void metodoMau() throws ExcecaoContabil {
if (!dadosCorretos) {
throw new ExcecaoContabil("Dados Incorretos");
}
}
public void metodoBom() {
try {
... instruções ...
metodoMau();
... instruções ...
} catch (ExcecaoContabil ex) {
System.out.println("Erro: " + ex.getMessage());
}
... instruções ...
}
}
instruções que sempre serão executadas
instruções que serão executadas se
a exceção não ocorrer
instruções serão executadas
se exceção não ocorrerou
se ocorrer e for capturada
16
try e catch
§ O bloco try "tenta" executar um bloco de
código que pode causar exceção
§ Deve ser seguido por
§ Um ou mais blocos
catch(TipoDeExcecao ref)
§ E/ou um bloco finally
§ Blocos catch recebem tipo de exceção
como argumento
§ Se ocorrer uma exceção no try, ela irá
descer pelos catch até encontrar um
que declare capturar exceções de uma
classe ou superclasse da exceção
§ Apenas um dos blocos catch é
executado
try {
... instruções ...
} catch (TipoExcecao1 ex) {
... faz alguma coisa ...
} catch (TipoExcecao2 ex) {
... faz alguma coisa ...
} catch (Exception ex) {
... faz alguma coisa ...
}
... continuação ...
17
finally
§ O bloco try não pode aparecer sozinho deve ser seguido por
pelo menos um catch ou por um finally
§ O bloco finally contém instruções que devem se executadas
independentemente da ocorrência ou não de exceções
try {
// instruções: executa até linha onde ocorrer exceção
} catch (TipoExcecao1 ex) {
// executa somente se ocorrer TipoExcecao1
} catch (TipoExcecao2 ex) {
// executa somente se ocorrer TipoExcecao2
} finally {
// executa sempre ...
}
// executa se exceção for capturada ou se não ocorrer
18
A Classe Exception
§ Construtores de Exception
§ Exception ()
§ Exception (String message)
§ Exception (String message, Throwable cause) [Java 1.4]
§ Métodos de Exception
§ String getMessage()
§ Retorna mensagem passada pelo construtor
§ Throwable getCause()
§ Retorna exceção que causou esta exceção [Java 1.4]
§ String toString()
§ Retorna nome da exceção e mensagem
§ void printStackTrace()
§ Imprime detalhes (stack trace) sobre exceção
19
Como pegar qualquer exceção
§ Se, entre os blocos catch, houver exceções da mesma
hierarquia de classes, as classes mais específicas (que
estão mais abaixo na hierarquia) devem aparecer primeiro
§ Se uma classe genérica (ex: Exception) aparecer antes
de uma mais específica, uma exceção do tipo da
específica jamais será capturado
§ O compilador detecta a situação acima e não compila o
código
§ Para pegar qualquer exceção (geralmente isto não é
recomendado), faça um catch que pegue Exception
catch (Exception e) { ... }
20
Relançar
§ Às vezes, após a captura de uma exceção, é desejável
relançá-la para que outros métodos lidem com ela
§ Isto pode ser feito da seguinte forma
public void metodo() throws ExcecaoSimples {
try {
// instruções
} catch (ExcecaoSimples ex) {
// faz alguma coisa para lidar com a exceção
throw ex; // relança exceção
}
}
21
Classes Bases
§ RuntimeException e Error
§ Exceções não verificadas em tempo de compilação
§ Subclasses de Error não devem ser capturadas (são situações
graves em que a recuperação é impossível ou indesejável)
§ Subclasses de RuntimeException representam erros de lógica
de programação que devem ser corrigidos (podem, mas não
devem ser capturadas: erros devem ser corrigidos)
§ Exception
§ Exceções verificadas em tempo de compilação (exceção à
regra são as subclasses de RuntimeException)
§ Compilador exige que sejam ou capturadas ou declaradas pelo
método que potencialmente as provoca
22
Hierarquia