aula tratamento de exceções
DESCRIPTION
Aula Algoritmos e Programação II - Tratamento de ExceçõesTRANSCRIPT
UNIVERSIDADE ESTADUAL DO SUDOESTE DA BAHIA CURSO DE CIÊNCIA DA COMPUTAÇÃO
ALGORITMOS E PROGRAMAÇÃO II – 2014.2
Fábio M. Pereira
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