Aula 8
Tratamento de exceções
-
- Exceções são situações excepcionais e geralmente indesejáveis que podem ocorrer
durante a execução de um programa. Exceções podem ser tratadas incluindo-se código
adequado no programa; não são portanto erros fatais.
- Exemplos típicos de exceções são:
- Índice de uma lista (
Array
) fora do intervalo permitido.
- Problemas em operações aritméticas, tais como "overflows" e divisões por zero.
- Argumentos inválidos numa chamada a um método.
- Uso de uma referência que não aponta para nenhum objeto.
- Falta de memória (relativamente improvável em Java graças ao coletor de lixo).
- O modelo de tratamento de exceções Java permite tratar uma exceção num escopo
(bloco de código) diferente daquele que gerou a exceção. Isto permite uma melhor organização
do código.
- Naturalmente, exceções são objetos em Java. A classe
Exception
é a superclasse de todas as exceções.
Existem vários tipos de exceções já definidos nas bibliotecas. O programador pode
também construir as suas próprias exceções.
- Muitas classes de biblioteca possuem métodos que podem gerar
("lançar") exceções. Estas exceções podem ser tratadas
("capturadas") por código escrito pelo programador.
Além disto, métodos escritos pelo programador também podem lançar exceções, tanto de
tipos definidos nas bibliotecas como de novos tipos construidos pelo programador.
-
Objetos que podem ser lançados para indicar que algo anormal aconteceu, e capturados
para lidar com esta situação, devem estender a classe
Throwable
do pacote
java.lang
. Os métodos mais úteis desta classe
são:
-
public String getMessage()
// retorna uma mensagem de erro
-
public void printStackTrace()
// imprime uma descrição da pilha no instante em que o problema ocorreu
Como já mencionado, a superclasse de todas as exceções é a classe
Exception
do pacote
java.lang
. Conforme indicado acima, esta classe
é uma subclasse da classe Throwable
. Existem um grande
número de subclasses de Exception
espalhadas
pelos vários pacotes de biblioteca. O programador pode estender a classe
Exception
ou uma das suas subclasses para construir
as suas próprias exceções.
Nem todos os problemas que podem ocorrer são considerados exceções. Problemas mais sérios,
que em geral não podem ser tratados pelo programador, são chamados
erros e são objetos da classe
Error
do pacote java.lang
(ou das subclasses desta classe, que também estão espalhadas pelos vários pacotes).
Erros não serão considerados aqui.
-
Uma exceção é lançada usando-se a palavra chave
throw
seguinda da referência à exceção. Exemplo:
Exception opa = new Exception( "deu zebra" );
...
if( temProblema ) throw opa;
Se o programador desejar que a exceção assim lançada seja tratada fora do método que
a gerou, ele deve explicitar isto usando a palavra chave
throws
seguida do tipo de exceção, na declaração
do método. Por exemplo, o código acima estaria inserido no corpo de um método declarado
como segue:
TipoDeRetorno nomeDoMetodo( ) throws Exception
{
// aqui vai o código acima
}
Na verdade, existe uma classe de exceções,
RuntimeException
(do pacote
java.lang
) que não precisam ser listadas
explicitamente após a palavra chave throws
.
Correspondentemente, não é mandatório para o programador incluir código para
manipular tais exceções.
Uma vez que a exceção foi lançada, a execução do método é interrompida e o controle
volta ao objeto que chamou este método. Este objeto deve capturar a exceção como descrito
a seguir, ou eventualmente relançar a exceção para que ela seja capturada mais alto na
hierarquia das chamadas de métodos.
-
Para capturar uma exceção, é necessário montar a seguinte estrutura de código.
- O código que pode lançar a exceção deve ser inserido num bloco precedido da palavra chave
try
. O processador então tentará executar o bloco,
até que eventualmente uma exceção seja lançada, seja por um comando contido dentro do
bloco, seja por um método chamado dentro do bloco.
- O bloco
try
descrito acima deve ser seguido de
um bloco que será executado caso houver de fato lançamento de uma exceção do tipo
em questão. Este bloco deve ser anunciado pela palavra chave
catch
seguida (entre parénteses) do tipo de exceção em questão. Se vários tipos de
exceções podem ser lançadas no bloco try
, deve-se
fornecer um bloco catch
para cada tipo de
exceção. Se uma exceção do tipo em questão for lançada no bloco
try
, o bloco try
é encerrado e a execução salta para o bloco catch
apropriado. Os blocos catch
são chamados
manipuladores de exceções.
- Ainda é possível acrescentar, após o(s) bloco(s)
catch
, um bloco precedido da palavra chave
finally
, que será executado em todos se casos, após
a execução completa do bloco try
ou após a
execução de um bloco catch
, conforme o caso.
Resumindo, a estrura é:
try
{
// aqui vai código que pode gerar exceções dos tipos
// ExceptionType1 e ExceptionType2
}
catch( ExceptionType1 opa1 )
{
// aqui vai código para lidar com uma exceção do tipo
// ExceptionType1
}
catch( ExceptionType2 opa2 )
{
// aqui vai código para lidar com uma exceção do tipo
// ExceptionType2
}
finally
{
// aqui vai código que deve ser executado em qualquer caso
}
Quando ocorre uma exceção, os blocos catch
são
examinados sucessivamente até que o argumento corresponda ao tipo da exceção. Note
que, no exemplo acima, se ExceptionType2
for uma subclasse de
ExceptionType1
, o segundo bloco catch
nunca será alcançado. Neste caso, deve-se inverter a ordem dos blocos
catch
.
Um bloco catch
pode também lançar novas exceções e
relançar a exceção que ele manipulou. Neste caso, todo o conjunto de blocos acima
deve estar inserido num bloco try
mais externo e
as exceções em questão devem ser manipuladas por blocos
catch
seguindo este bloco
try
externo.