aula tratamento de exceções

Post on 09-Jul-2015

191 Views

Category:

Education

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Aula Algoritmos e Programação II - Tratamento de Exceções

TRANSCRIPT

UNIVERSIDADE ESTADUAL DO SUDOESTE DA BAHIA CURSO DE CIÊNCIA DA COMPUTAÇÃO

ALGORITMOS E PROGRAMAÇÃO II – 2014.2

Fábio M. Pereira

(fabio.mpereira@uesb.edu.br)

Roteiro

• O que é uma exceção?

• Requisito de captura ou especificação

• Capturando e manipulando exceções

• Especificando as exceções lançadas por um método

• Como lançar exceções

• Vantagens de exceções

O que é uma exceção?

• Exceção á uma abreviação para a frase “evento excepcional”

• Definição: – Uma exceção é um evento, que ocorre durante a execução de

um programa, que interrompe o fluxo normal de instruções do programa

• Quando um erro ocorre, dentro de um método, o método cria um objeto e o envia para o sistema de execução

• Este “objeto de exceção” contém informação sobre o erro, incluindo o seu tipo e o estado do programa quando o erro ocorreu – Criar uma exceção e enviá-la ao sistema de execução é o que

chamamos de lançar uma exceção

O que é uma exceção?

• Após o método lançar uma exceção, o sistema de execução tenta encontrar alguma coisa para manipulá-la

• O conjunto de possíveis “coisas” para manipular uma exceção é a lista ordenada de métodos que são chamados para chegar ao método onde o erro ocorreu

– Esta lista de métodos é conhecida como pilha de chamada

main

Método com um manipulador de exceção

Método sem um manipulador de exceção

Método onde o erro ocorreu

Chamada de método

Chamada de método

Chamada de método

O que é uma exceção?

• O sistema de execução busca na pilha de chamada por um método que contém um bloco de código que pode manipular a exceção

• Este bloco de código é chamado de manipulador de exceção

• A busca iniciar no método em que o erro ocorreu e continua através da pilha de chamada em ordem inversa na qual os métodos foram chamados

• Quando o manipulador apropriado é encontrado, o sistema de execução passa a exceção ao manipulador

• Um manipulador de exceção é considerado apropriado se o tipo do objeto de exceção lançado combina com o tipo que pode ser manipulado pelo manipulador

O que é uma exceção?

• A escolha do manipulador de exceção é chamada de capturar a exceção

• Se a busca do sistema de execução na pilha de chamada não encontrar um manipulador de exceção apropriado, o sistema de execução e o programa são interrompidos

main

Método com um manipulador de exceção

Método sem um manipulador de exceção

Método onde o erro ocorreu

Busca pelo manipulador apropriado

Busca pelo manipulador apropriado

Lançamento de exceção

Envia exceção para frente

Captura alguma outra exceção

Requisito de captura o especificação

• Um código válido na linguagem Java deve honrar o Requisito de Captura ou Especificação

• Isto significa que o código que pode lançar certas exceções deve estar delimitado por um dos seguintes: – Uma instrução try que captura a exceção – o try deve fornecer

um manipulador para a exceção

– Um método que especifica que uma exceção pode ser lançada – o método deve fornecer uma cláusula throws que lista a exceção

• O código que falhar em honrar o requisito de captura ou especificação não será compilado

• Nem todas as exceções estão sujeita a este requisito – Para entender o porquê, precisamos analisar as três categorias

de exceções, onde apenas uma está sujeita ao requisito

Os três tipos de exceções

• O primeiro tipo de exceção é a exceção verificada – Estas são condições excepcionais que uma aplicação bem escrita deve

antecipar e se recuperar delas

• Por exemplo, – Suponha que uma aplicação peça ao usuário por um nome de arquivo

de entrada, então abra o arquivo passando o nome ao construtor de java.io.FileReader

– Normalmente o usuário fornece um nome de um arquivo que possa ser lido e que exista, assim a construção do objeto FileReader é bem sucedida e a execução da aplicação procede normalmente

– Mas algumas vezes o usuário pode fornecer um nome de um arquivo que não exista e o construtor lança java.io.FileNotFoundException

– Um programa bem escrito irá capturar esta exceção e notificar o usuário do erro, possibilitando que ele entre com um nome de arquivo correto

Os três tipos de exceções

• Exceções verificadas estão sujeitas ao requisito de captura ou especificação

• Todas as exceções são exceções verificadas, exceto aquelas indicadas por Error, RuntimeException e suas subclasses

Os três tipos de exceções

• O segundo tipo de exceção é o erro

– Estes são condições excepcionais que são internas à aplicação e que a aplicação normalmente não pode antecipar ou se recuperar

• Por exemplo,

– Suponha que uma aplicação abra uma arquivo para entrada com sucesso, mas não consiga ler o arquivo por causa de uma falha de hardware ou de sistema

– A leitura mal sucedida ira lançar java.io.IOError

– Uma aplicação poderia escolher capturar esta exceção, de maneira a notificar o usuário do problema, mas também faria sentido para o programa imprimir um rastreamento de pilha e sair

Os três tipos de exceções

• Erros não estão sujeitos ao requisito de captura ou especificação

• Erros são exceções indicadas por Error e suas subclasses

Os três tipos de exceções

• O terceiro tipo de exceção é a exceção runtime – Estas são condições excepcionais que são internas à aplicação e

que a aplicação normalmente não pode antecipar ou se recuperar

– Normalmente representam erros no programa, como erros lógicos ou uso não apropriado de uma API

• Por exemplo, – Considerando a aplicação descrita anteriormente que passa um

nome de arquivo ao construtor FileReader

– Se um erro lógico causar um valor null ser passado para o construtor, este irá lançar NullPointerException

– A aplicação pode capturar esta exceção, mas provavelmente faz mais sentido eliminar o erro que causou a ocorrência da exceção

Os três tipos de exceções

• Exceções runtime não estão sujeitas ao requisito de captura ou especificação

• Exceções runtime são aquelas indicadas por RuntimeException e suas subclasses

• Erros e exceções runtime são conhecidas como exceções não verificadas

Ignorando captura ou especificação

• Alguns programadores consideram o Requisito de Captura ou Especificação uma falha grave no mecanismo de exceção e os ignoram usando exceções não verificadas no lugar de exceções verificadas

• Em geral isto não é recomendado

Capturando e manipulando exceções

• Onde veremos como utilizar os três componentes de manipulação de eventos: os blocos try, catch e finally

• O exemplo a seguir define e implementa uma classe chamada ListaDeNumeros

Exemplo

Exemplo

Exemplo

• A primeira linha em destaque é a chamada a um construtor – O construtor inicializa um fluxo de saída em um arquivo

– Se o arquivo não puder ser aberto, o construtor lança uma IOException

• A segunda linha em destaque é uma chamada ao método elementAt da classe Vector, que lança uma ArrayIndexOutOfBoundsException se o valor de seu argumento for muito pequeno (menor que zero) ou muito grande (maior que o número de elementos existentes atualmente no Vector

• Se tentarmos compilar a classe ListaDeNumeros, o compilador irá imprimir uma mensagem de erro sobre a exceção lançada pelo construtor FileWriter, embora não mostre uma mensagem de erro sobre a exceção lançada por elementAt

Exemplo

• Isto ocorre porque a exceção lançada pelo construtor, IOException, é uma exceção verificada, e a lançada pelo método elementAt, ArrayIndexOutOfBoundsException, é uma exceção não verificada

• Vamos agora escrever os manipuladores de exceção para capturar e manipular estas exceções

O bloco try

• O primeiro passo na construção de um manipulador de exceções é delimitar o código que pode lançar uma exceção dentro de um bloco try que, em geral, se parece com: try {

código

}

blocos catch e finally ...

• O segmento rotulado código contém uma ou mais linhas de código que poderiam lançar uma exceção

• Podemos colocar cada linha de código que pode lançar uma exceção dentro de seu próprio bloco try e fornecer manipuladores de exceção separados para cada uma ou colocar todo o código dentro de um único bloco try e associá-lo a múltiplos manipuladores

Exemplo

Os blocos catch

• Se uma exceção ocorrer dentro do bloco try, a exceção é manipulada pelo manipulador de exceção associado a ele – Para associar um manipular de exceção com um bloco try, devemos

colocar um bloco catch logo após ele

• Devemos colocar um ou mais blocos catch após o bloco try

– Não pode haver código entre o final do bloco try e o início do primeiro bloco catch:

try {

} catch (TipoDeExceção nome) {

} catch (TipoDeExceção nome) {

}

Os blocos catch

• Cada bloco catch é um manipulador de exceção e manipula o tipo de exceção indicado em seu argumento

– O tipo do argumento, TipoDeExceção, declara o tipo de exceção que o manipulador pode manipular e deve ser o nome de uma classe que herda da classe Throwable

– O manipulador pode referenciar a exceção através de nome

• O exemplo mostra dois manipuladores de exceção para o método imprimeLista

Exemplo

• Ambos os manipuladores imprimem uma mensagem de erro, mas o segundo não faz mais nada além disso, capturando uma IOException que não for capturada pelo primeiro manipulador, ele permite que o programa continue a sua execução

Exemplo

• O primeiro manipulador, além de imprimir uma mensagem, lança uma exceção definida pelo usuário, ExcecaoExemplo

– Usamos isto quando queremos que o programa manipule uma exceção de uma maneira específica

• Manipuladores de exceção podem fazer mais que apenas imprimir uma mensagem de erro ou abortar o programa

– Elas podem se recuperar do erro, pedir para o usuário tomar uma decisão ou propagar o erro para um nível mais alto de manipulação usando exceções encadeadas

O bloco finally

• O bloco finally sempre é executado quando o programa sai do bloco try

– Isto garante que o bloco finally seja executado mesmo que uma exceção não esperada ocorra

• finally é útil para evitar que código de limpeza seja eventualmente ignorado por um return, continue ou break

– Colocar código de limpeza em finally é sempre uma boa prática, mesmo que nenhuma exceção seja antecipada

• O método imprimeLista abre um PrintWriter

– Devemos garantir que o programa feche o arquivo antes de sair do método

O bloco finally

• Isto pode ser complicado, uma vez que o bloco try de imprimeLista pode sair em uma das três maneiras:

1. A instrução new FileWriter falha e lança uma IOException

2. A instrução vetor.elementAt(i) falha e lança uma ArrayIndexOutOfBoundsException

3. Tudo é executado e o bloco try sai normalmente

• O sistema de execução sempre executa instruções dentro do bloco finally independente do que aconteça no bloco try, sendo então um lugar perfeito para realizar limpeza

Exemplo

Colocando tudo junto

Cenário 1 – uma exceção ocorre

Cenário 2 – execução normal

Especificando as exceções lançadas por um método

• Algumas vezes é apropriado que o código capture exceções que possam ocorrer dentro dele

• Em outros casos, é melhor deixar um método mais acima na pilha de chamadas tratar a exceção

• Por exemplo, se estivermos fornecendo a classe ListaDeNumeros como parte de um pacote de classes, provavelmente não poderíamos antecipar as necessidades de todos os usuários do pacote

– Neste caso, é melhor não capturar a exceção e permitir que um método mais acima na pilha de chamadas lide com isso

Especificando as exceções lançadas por um método

• Se o método imprimirLista não capturar as exceções verificadas que podem ocorrer dentro dele, o método deve especificar que ele pode lançar essas exceções

• Vamos modificar o método imprimeLista original para especificar as exceções que podem ser lançadas, em vez de capturá-las

• Programa original:

Especificando as exceções lançadas por um método

• Para especificar que imprimeLista pode lançar duas exceções, adicionamos uma cláusula throws na declaração do método: public void imprimeLista() throws IOException,

ArrayIndexOutOfBoundsException {

• Lembrando que ArrayIndexOutOfBoundsException é uma exceção não verificada, assim, incluí-la na cláusula throws não é obrigatório: public void imprimeLista() throws IOException {

Como lançar exceções

• Antes de podermos capturar uma exceção, algum código em algum lugar deve lançá-la

• Qualquer código pode lançar uma exceção: o seu código, o código de um pacote escrito por outra pessoa, como os pacotes que vêm com a plataforma Java, ou o ambiente de execução Java

• Independentemente do que lança a exceção, ela é sempre lançada com a instrução throw

• A plataforma Java oferece inúmeras classes de exceção – Todas as classes são descendentes da classe throwable e todas

elas permitem aos programas diferenciar entre os vários tipos de exceções que podem ocorrer durante a execução de um programa

Como lançar exceções

• Também podemos criar nossas próprias classes de exceção para representar problemas que podem ocorrer dentro das classes que escrevemos

• Na verdade, se desenvolvemos pacotes, podemos ter que criar o nosso próprio conjunto de classes de exceção para permitir aos usuários diferenciarem um erro que pode ocorrer em nosso pacote de erros que ocorrem na plataforma Java ou outros pacotes

A instrução throw

• Todos os métodos usam a instrução throw para lançar uma exceção

• A instrução throw requer um único argumento: um objeto throwable

• Objetos throwable objetos são instâncias de qualquer subclasse da classe Throwable

• Aqui está um exemplo de uma instrução throw: throw algumObjetoThrowable;

A instrução throw

• Vamos olhar para a instrução throw em contexto: – O seguinte método pop foi retirado de uma classe de objeto que

implementa uma pilha comum – O método remove o elemento do topo da pilha e retorna o objeto public Object pop() {

Object obj;

if (tamanho == 0) {

throw new EmptyStackException();

}

obj = objetoEm(tamanho - 1);

setObjetoEm(tamanho - 1, null);

tamanho--;

return obj;

}

A classe Throwable e suas subclasses

• Os objetos que herdam da classe Throwable incluem descendentes diretos e descendentes indiretos (objetos que herdam de filhos ou netos da classe Throwable)

• Como podemos ver, Throwable tem dois descendentes diretos: Error e Exception

A classe Error

• Quando uma falha de ligação dinâmica ou outra falha importante na máquina virtual Java ocorre, a máquina virtual gera um Error

• Programas simples, normalmente, não capturam ou lançam Errors

A classe Exception

• A maioria dos programas lançam e capturam objetos que derivam da classe Exception

• Uma Exception indica que ocorreu um problema, mas não é um problema grave no sistema

• A maioria dos programas que escrevemos lançam e capturam Exceptions em oposição a Errors

• A plataforma Java define os muitos descendentes da classe Exception

• Estes descendentes indicam vários tipos de exceções que podem ocorrer

• Por exemplo, IllegalAccessException indica que um determinado método não pôde ser encontrado, e NegativeArraySizeException indica que um programa tentou criar uma matriz com um tamanho negativo

A classe Exception

• Uma subclasse de Exception, RuntimeException, é reservada para as exceções que indicam o uso incorreto de uma API

• Um exemplo de uma exceção de tempo de execução é NullPointerException, que ocorre quando um método tenta acessar um membro de um objeto através de uma referência nula

A hierarquia de classes Throwable

Acessando a pilha de informação de rastreamento

• Um rastreamento de pilha fornece informações sobre o histórico de execução do segmento atual e lista os nomes das classes e métodos que foram chamados no momento em que ocorreu a exceção

• Um rastreamento de pilha é uma ferramenta de depuração útil que normalmente tiramos proveito quando uma exceção é acionada

• O exemplo seguinte mostra como chamar o método getStackTrace do objeto de exceção

Acessando a pilha de informação de rastreamento

catch (Exception e) {

StackTraceElement elementos[] = e.getStackTrace();

for (int i=0, n=elementos.length; i<n; i++) {

System.err.println(elementos[i].getFileName()

+ ":" + elementos[i].getLineNumber()

+ ">> " + elementos[i].getMethodName()

+ "()");

}

}

Vantagens de exceções

• Separar o código de tratamento de erros de código “regular”

– Exceções fornecem os meios para separar os detalhes do que fazer quando algo fora do comum acontece da lógica principal de um programa

– Na programação tradicional, a detecção de erros, relatórios e manipulação conduzem frequentemente a código confuso

• Propagar erros na pilha de chamadas

– Uma segunda vantagem de exceções é a capacidade de propagar o erro relatando a pilha de chamadas de métodos

Vantagens de exceções

• Agrupar e diferenciar tipos de erro

– Uma vez que todas as exceções lançadas dentro de um programa são objetos, o agrupamento ou categorização de exceções é um resultado natural da hierarquia de classes

– Um exemplo de um grupo de classes de exceção relacionadas na plataforma Java são aquelas definidas em java.ioIOException e seus descendentes

– IOException é o mais geral e representa qualquer tipo de erro que pode ocorrer durante a execução de I/O

– Seus descendentes representam erros mais específicos, por exemplo, FileNotFoundException significa que um arquivo não pôde ser localizado no disco

Referências

The Java Tutorial Fourth Edition: A Short Course on the Basics

Sharon Zakhour, Scott Hommel, Jacob Royal, Isaac Rabinovitch, Tom Risser, Mark Hoeber

...............................................

Publisher: Addison Wesley Professional

Pub Date: September 29, 2006

UNIVERSIDADE ESTADUAL DO SUDOESTE DA BAHIA CURSO DE CIÊNCIA DA COMPUTAÇÃO

ALGORITMOS E PROGRAMAÇÃO II – 2014.2

Fábio M. Pereira

(fabio.mpereira@uesb.edu.br)

top related