Baixe o app para aproveitar ainda mais
Prévia do material em texto
Tratamento de exceções APRESENTAÇÃO Exceções são erros que ocorrem em tempo de execução. Usando uma linguagem de programação, você pode tratar erros de tempo de execução de forma estruturada e controlada. As exceções podem ser uma simples divisão por zero ou a resposta a algum erro interno. Tratar exceções também impede que nosso programa possa terminar de forma anormal. Nesta Unidade de Aprendizagem veremos o tratamento de exceções e a importância desta técnica para sua aplicação. Bons estudos. Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados: Analisar tratamento de exceções.• Usar try e catch.• Construir uma aplicação utilizando as técnicas de tratamento de exceção.• DESAFIO Exceções podem ocorrer na execução de uma aplicação. Podemos citar como exemplo o fato de uma entrada de dados lançada pelo usuário, que deveria ser um número inteiro, e, por algum motivo, o usuário digita um caractere. Caso não seja tratado, a aplicação pode terminar de forma anormal. Você trabalha como analista/programador em uma fábrica de software. Um dos clientes está com um problema; sua aplicação é uma calculadora que funciona recebendo dois números, e o cliente informa uma das quatro operações básicas da matemática (adição, subtração, multiplicação e divisão). O que ocorre é que quando o usuário digita um valor que não seja um número decimal, a aplicação gera um erro e encerra. Sua tarefa é implementar um tratamento de exceções nesta aplicação. INFOGRÁFICO O infográfico a seguir mostra o conceito de tratamento de exceções. CONTEÚDO DO LIVRO Uma exceção é um erro que ocorre no tempo de execução. Usando o subsistema Java de tratamento de exceções, você pode tratar erros de tempo de execução de maneira estruturada e controlada. Acompanhe um trecho do livro Java para iniciantes, obra que serve de base teórica para esta Unidade de Aprendizagem e traz uma abordagem sobre tratamento de exceções. Inicie o estudo no tópico Principais habilidades e conceitos e finalize ao final de Consequências de uma exceção não capturada. Atualizado para JAVA SE 8 (JDK 8) Java para iniciantes Crie, compile e execute programas Java rapidamente Herbert Schildt Catalogação na publicação: Poliana Sanchez de Araujo – CRB 10/2094 S334j Schildt, Herbert. Java para iniciantes : crie, compile e execute programas Java rapidamente [recurso eletrônico] / Herbert Schildt ; tradução: Aldir José Coelho Corrêa da Silva ; revisão técnica: Maria Lúcia Blanck Lisbôa. – 6. ed. – Porto Alegre : Bookman, 2015. Editado como livro impresso em 2015. ISBN 978-85-8260-337-6 1. Linguagem de programação - Java. I. Título. CDU 004.438Java O autor O autor de best-sellers Herbert Schildt escreve incansavelmente sobre programação há quase três décadas e é uma das principais autoridades na linguagem Java. Seus livros de programação venderam milhões de cópias no mundo inteiro e foram tra- duzidos para diversos idiomas. É autor de vários livros sobre Java, incluindo Java: The Complete Reference, Herb Schildt’s Java Programming Cookbook e Swing: A Beginner’s Guide. Ele também escreveu sobre C, C++ e C#. Embora tenha interesse em todas as áreas da computação, seu foco principal são as linguagens de progra- mação, incluindo compiladores, interpretadores e linguagens de controle robótico. Também tem grande interesse na padronização de linguagens. Schildt tem gradua- ção e pós-graduação pela Universidade de Illinois. Seu site é www.HerbSchildt.com. O editor técnico Dr. Danny Coward trabalhou em todas as edições da plataforma Java. Ele conduziu a definição dos Java Servlets para a primeira versão da plataforma Java EE e para além dela, os serviços web para a plataforma Java ME, e a estratégia e planejamento de Java SE 7. Fundou a tecnologia JavaFX e, mais recentemente, projetou o maior acréscimo feito ao padrão Java EE 7, a API Java WebSocket. Da codificação em Java ao projeto de APIs com especialistas da indústria e ao trabalho por vários anos como executivo do Java Community Process, ele adquiriu uma perspectiva singularmente ampla de vários aspectos da tecnologia Java. Além disso, é autor de JavaWebSo- cket Programming e de um livro ainda a ser publicado sobre Java EE. Dr. Coward tem graduação, mestrado e doutorado em Matemática pela Universidade de Oxford. Capítulo 9 Tratamento de exceções 293 Principais habilidades e conceitos • Conhecer a hierarquia de exceções • Usar try e catch • Entender os efeitos de uma exceção não capturada • Usar várias instruções catch • Capturar exceções de subclasse • Aninhar blocos try • Lançar uma exceção • Saber os membros de Throwable • Usar finally • Usar throws • Conhecer as exceções internas Java • Criar classes de exceção personalizadas ..................................................................................................................................... Este capítulo discutirá o tratamento de exceções. Uma exceção é um erro que ocorre no tempo de execução. Usando o subsistema Java de tratamento de exce- ções, você pode tratar erros de tempo de execução de maneira estruturada e controla- da. Embora a maioria das linguagens de programação modernas ofereça algum tipo de tratamento de exceções, o suporte Java é fácil de usar e flexível. A principal vantagem do tratamento de exceções é que ele automatiza grande parte do código de tratamento de erros que antigamente tinha que ser inserido “à mão” em qualquer programa grande. Por exemplo, em algumas linguagens de computador mais antigas, os códigos de erro são retornados quando um método falha e esses valo- res devem ser verificados manualmente sempre que o método é chamado. Essa aborda- gem é, ao mesmo tempo, tediosa e propensa a erros. O tratamento de exceções otimiza o tratamento de erros, permitindo que o programa defina um bloco de código, chama- do tratador de exceções, executado automaticamente quando um erro ocorre. Não é necessário verificar manualmente o sucesso ou a falha de cada chamada de método ou operação específica. Se um erro ocorrer, ele será processado pelo tratador de exceções. Outra razão que torna o tratamento de exceções importante é Java definir ex- ceções padrão para erros que são comuns nos programas, como a divisão por zero ou um arquivo não encontrado. Para reagir a esses erros, seu programa deve estar alerta a esse tipo de exceção e tratá-las. Além disso, a biblioteca de APIs Java usa intensamente exceções. No fim das contas, ser um programador de Java bem-sucedido significa ser plenamente capaz de navegar no subsistema de tratamento de exceções Java. 294 Java para Iniciantes Hierarquia de exceções Em Java, todas as exceções são representadas por classes e todas as classes de exce- ções são derivadas de uma classe chamada Throwable. Logo, quando uma exceção ocorre em um programa, um objeto de algum tipo de classe de exceção é gerado. Há duas subclasses diretas de Throwable: Exception e Error. As exceções de tipo Error estão relacionadas a erros que ocorrem na própria máquina virtual Java e não nos programas. Esses tipos de exceções fogem ao nosso controle e geralmente os programas não lidam com elas. Portanto, não serão descritas aqui. Erros que resultam da atividade do programa são representados por subclasses de Exception. Por exemplo, erros de divisão por zero, que excedem os limites do array e relacionados a arquivos se enquadram nessa categoria. Em geral, os progra- mas devem tratar exceções desses tipos. Uma subclasse importante de Exception é RuntimeException, que é usada para representar vários tipos comuns de erros de tempo de execução. Fundamentos do tratamento de exceções O tratamento de exceções Java é gerenciado por cinco palavras-chave: try, catch, throw, throws e finally. Elas formam um subsistema interligado em que o uso de uma implica o uso de outra. No decorrer deste capítulo, examinaremos cada palavra- -chave com detalhes. No entanto, é útil termosdesde o início uma compreensão geral do papel que cada uma desempenha no tratamento de exceções. Resumidamente, veja como funcionam. As instruções do programa que você quiser monitorar em busca de exceções ficarão dentro de um bloco try. Se uma exceção ocorrer dentro do bloco try, ela será lançada. Seu código poderá capturar essa exceção usando catch e tratá-la de alguma maneira racional. Exceções geradas pelo sistema são lançadas automati- camente pelo sistema de tempo de execução Java. Para lançar manualmente uma exceção, use a palavra-chave throw. Em alguns casos, uma exceção que é lançada para fora de um método deve ser especificada como tal por uma cláusula throws. Qualquer código que deva ser executado ao sair de um bloco try deve ser inserido em um bloco finally. P: Para não deixar dúvidas, você poderia descrever novamente as condições que fazem uma exceção ser gerada? R: Exceções são geradas de três maneiras diferentes. Em primeiro lugar, a Máquina Vir- tual Java pode gerar uma exceção em reposta a algum erro interno sobre o qual não tenhamos controle. Normalmente, o programa não trata esses tipos de exceções. Em segundo lugar, exceções padrão, como as correspondentes à divisão por zero ou índi- ces fora dos limites de um array, são geradas por erros no código do programa. Temos que tratar essas exceções. Em terceiro lugar, podemos gerar manualmente uma exce- ção usando a instrução throw. Independentemente de como uma exceção for gerada, ela será tratada da mesma forma. Pergunte ao especialista Capítulo 9 Tratamento de exceções 295 Usando try e catch As palavras-chave try e catch formam a base do tratamento de exceções. Elas fun- cionam em conjunto, ou seja, você não pode ter um catch sem ter um try. Esta é a forma geral dos blocos try/catch de tratamento de exceções: try { // bloco de código cujos erros estão sendo monitorados } catch (TipoExceç1 obEx) { // tratador de TipoExceç1 } catch (TipoExceç2 obEx) { // tratador de TipoExceç2 } . . . Aqui, TipoExceç é o tipo de exceção que ocorreu. Quando uma exceção é lançada, ela é capturada pela instrução catch correspondente, que então a processa. Como a forma geral mostra, podemos ter mais de uma instrução catch associada a uma ins- trução try. O tipo da exceção determina que instrução catch será executada. Isto é, se o tipo de exceção especificado por uma instrução catch coincidir com o da exce- ção ocorrida, essa instrução catch será executada (e todas as outras serão ignoradas). Quando uma exceção é capturada, obEx recebe seu valor. Agora um ponto importante: se nenhuma exceção for lançada, o bloco try ter- minará normalmente e todas as suas instruções catch serão ignoradas. A execução será retomada na primeira instrução após o último catch. Logo, as instruções catch só são executadas quando ocorre uma exceção. NOTA A partir de JDK 7, há outra forma de instrução try que dá suporte ao gerenciamento automático de recursos. Essa nova forma de try se chama try-with-resources. Ela é descrita no Capítulo 10, no contexto do gerenciamento de fluxos de I/O (como os conectados a um arquivo), porque os fluxos são um dos recursos mais usados. Exemplo de exceção simples Este é um exemplo simples que ilustra como monitorar uma exceção e capturá-la. Como você sabe, é um erro tentar indexar um array além de seus limites. Quando isso ocorre, a JVM lança uma ArrayIndexOutOfBoundsException. O programa a seguir gera intencionalmente essa exceção e então a captura: // Demonstra o tratamento de exceções. class ExcDemo1 { public static void main(String args[]) { int nums[] = new int[4]; try { Cria um bloco try. 296 Java para Iniciantes System.out.println("Before exception is generated."); // Gera um exceção de índice fora dos limites. nums[7] = 10; System.out.println("this won't be displayed"); } catch (ArrayIndexOutOfBoundsException exc) { // captura a exceção System.out.println("Index out-of-bounds!"); } System.out.println("After catch statement."); } } Esse programa exibirá a saída abaixo: Before exception is generated. Index out-of-bounds! After catch statement. Embora bem curto, o programa anterior ilustra vários pontos-chave do trata- mento de exceções. Em primeiro lugar, o código cujos erros você quer monitorar está dentro de um bloco try. Em segundo lugar, quando ocorre uma exceção (nesse caso, pela tentativa de indexar nums além de seus limites), ela é lançada fora do bloco try e capturada pela instrução catch. Nesse ponto, o controle passa para catch e o bloco try é encerrado. Isto é, catch não é chamada. Em vez disso, a execução do programa é transferida para ela. Logo, a instrução println( ) que vem após o índice fora do limite nunca será executada. Após a instrução catch ser executada, o controle do programa continua nas instruções seguintes a catch. Portanto, é função do trata- dor de exceções remediar o problema que causou a exceção, para que a execução do programa possa continuar normalmente. Lembre-se, se nenhuma exceção for lançada por um bloco try, nenhuma ins- trução catch será executada e o controle do programa será retomado após a instrução catch. Para confirmar isso, no programa anterior, mude a linha nums[7] = 10; para nums[0] = 10; Agora, nenhuma exceção é gerada e o bloco catch não é executado. É importante entender que as exceções do código que fica dentro de um blo- co try estão sendo monitoradas. Isso inclui exceções que podem ser geradas por um método chamado de dentro do bloco try. Uma exceção lançada por um método chamado de dentro de um bloco try pode ser capturada pelas instruções catch as- sociadas a esse bloco try – presumindo, claro, que o próprio método não capture a exceção. Por exemplo, este é um programa válido: /* Uma exceção pode ser gerada por um método e capturada por outro. */ class ExcTest { Tenta indexar excedendo o limite de nums. Captura erros nos limites do array. Capítulo 9 Tratamento de exceções 297 // Gera uma exceção. static void genException() { int nums[] = new int[4]; System.out.println("Before exception is generated."); // gera uma exceção de índice fora do limite nums[7] = 10; System.out.println("this won't be displayed"); } } class ExcDemo2 { public static void main(String args[]) { try { ExcTest.genException(); } catch (ArrayIndexOutOfBoundsException exc) { // captura a exceção System.out.println("Index out-of-bounds!"); } System.out.println("After catch statement."); } } Esse programa produz a saída a seguir, que é igual à produzida pela primeira versão mostrada anteriormente: Before exception is generated. Index out-of-bounds! After catch statement. Já que genException( ) é chamado de dentro de um bloco try, a exceção que ele gera (e não captura) é capturada pela instrução catch de main( ). No entanto, é bom ressaltar que se genException( ) tivesse capturado a exceção, ela nunca teria sido passada para main( ). Consequências de uma exceção não capturada Capturar uma das exceções padrão Java, como fez o programa anterior, tem um be- nefício adicional: impede que o programa seja encerrado de modo anormal. Quando uma exceção é lançada, ela deve ser capturada por um código em algum local. Em geral, quando o programa não captura uma exceção, ela é capturada pela JVM. O problema é que o tratador de exceções padrão da JVM encerra a execução e exibe um rastreamento de pilha e uma mensagem de erro. Por exemplo, nesta versão do exemplo anterior, a exceção de índice fora do limite não é capturada pelo programa. // Deixa a JVM tratar o erro. class NotHandled { public static void main(String args[]) { int nums[] = new int[4]; A exceção é gerada aqui. A exceção é capturada aqui. 298 Java para Iniciantes System.out.println("Before exception is generated."); // gera uma exceção de índice fora do limite nums[7] = 10;} } Quando ocorre o erro de indexação do array, a execução é interrompida, e a mensagem de erro a seguir é exibida. Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 7 at NotHandled.main(NotHandled.java:9) Embora essa mensagem seja útil na depuração, no mínimo não seria algo que você gostaria que outras pessoas vissem! Por isso, é importante seu programa tratar ele próprio as exceções, em vez de depender da JVM. Como mencionado anteriormente, o tipo da exceção deve coincidir com o tipo especificado em uma instrução catch. Se não coincidir, a exceção não será captura- da. Por exemplo, o programa abaixo tenta capturar um erro no limite do array com a instrução catch de uma ArithmeticException (outra das exceções internas Java). Quando o limite do array é excedido, uma ArrayIndexOutOfBoundsException é gerada, mas não será capturada pela instrução catch. Isso resulta no programa sendo encerrado de modo anormal. // Não funcionará! class ExcTypeMismatch { public static void main(String args[]) { int nums[] = new int[4]; try { System.out.println("Before exception is generated."); //gera uma exceção de índice fora do limite nums[7] = 10; System.out.println("this won't be displayed"); } /* Não pode capturar um erro de limite de array com uma ArithmeticException. */ catch (ArithmeticException exc) { // captura a exceção System.out.println("Index out-of-bounds!"); } System.out.println("After catch statement."); } } A saída é mostrada aqui: Before exception is generated. Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 7 at ExcTypeMismatch.main(ExcTypeMismatch.java:10) Essa linha lança uma ArrayIndexOutOfBoundsException. Essa linha tenta capturá-la com uma ArithmeticException. Capítulo 9 Tratamento de exceções 299 Como a saída mostra, a instrução catch de uma ArithmeticException não captura uma ArrayIndexOutOfBoundsException. Exceções permitem que você trate erros normalmente Um dos principais benefícios do tratamento de exceções é que ele permite que seu programa responda a um erro e então continue a ser executado. Por exemplo, con- sidere o caso a seguir que divide os elementos de um array pelos de outro. Se uma divisão por zero ocorrer, uma AritmethicException será gerada. No programa, essa exceção é tratada pelo relato do erro e a execução continua. Logo, tentar dividir por zero não causa um erro abrupto de tempo de execução resultando no enceramento do programa. Em vez disso, a situação é tratada normalmente, permitindo que a execu- ção do programa continue. // Trata o erro normalmente e continua a execução. class ExcDemo3 { public static void main(String args[]) { int numer[] = { 4, 8, 16, 32, 64, 128 }; int denom[] = { 2, 0, 4, 4, 0, 8 }; for(int i=0; i<numer.length; i++) { try { System.out.println(numer[i] + " / " + denom[i] + " is " + numer[i]/denom[i]); } catch (ArithmeticException exc) { // captura a exceção System.out.println("Can't divide by Zero!"); } } } } A saída do programa é mostrada abaixo: 4 / 2 is 2 Can't divide by Zero! 16 / 4 is 4 32 / 4 is 8 Can't divide by Zero! 128 / 8 is 16 Esse exemplo ilustra outro ponto importante: uma vez que uma exceção foi tratada, ela é removida do sistema. Portanto, no programa, cada vez que o laço é percorrido, entramos novamente no bloco try; qualquer exceção anterior terá sido tratada. Isso permite que seu programa trate erros repetidos. Usando várias instruções catch Como mencionado, você pode associar mais de uma instrução catch a uma instrução try. Na verdade, isso é comum. No entanto, cada catch deve capturar um tipo de 300 Java para Iniciantes exceção diferente. Por exemplo, o programa mostrado aqui captura erros tanto de limite de array quanto de divisão por zero: // Usa várias instruções catch. class ExcDemo4 { public static void main(String args[]) { // Aqui, numer é maior do que denom. int numer[] = { 4, 8, 16, 32, 64, 128, 256, 512 }; int denom[] = { 2, 0, 4, 4, 0, 8 }; for(int i=0; i<numer.length; i++) { try { System.out.println(numer[i] + " / " + denom[i] + " is " + numer[i]/denom[i]); } catch (ArithmeticException exc) { // captura a exceção System.out.println("Can't divide by Zero!"); } catch (ArrayIndexOutOfBoundsException exc) { // captura a exceção System.out.println("No matching element found."); } } } } Esse programa produz a saída a seguir: 4 / 2 is 2 Can't divide by Zero! 16 / 4 is 4 32 / 4 is 8 Can't divide by Zero! 128 / 8 is 16 No matching element found. No matching element found. Como a saída confirma, cada instrução catch responde apenas ao seu tipo de exceção. Em geral, as expressões catch são verificadas na ordem em que ocorrem em um programa. Só uma instrução que apresente correspondência é executada. Todos os outros blocos catch são ignorados. Várias instruções catch Encerra aqui o trecho do livro disponibilizado para esta Unidade de Aprendizagem. Na Biblioteca Virtual da Instituição, você encontra a obra na íntegra. DICA DO PROFESSOR Assista ao vídeo e veja o uso das instruções try-catch. Conteúdo interativo disponível na plataforma de ensino! EXERCÍCIOS 1) Com relação ao tratamento de exceções, marque a alternativa incorreta. A) Exceções são erros de execução. B) Erros de tempo de execução não podem ser tratados. C) O tratamento de exceções automatiza grande parte do código de tratamento de erros. D) A linguagem de programação java define exceções-padrão para erros que são comuns nos programas. E) O tratamento de exceções permite que o programa defina um bloco de códigos chamado tratador de exceções. 2) O tratamento de exceções em java é gerenciado por cinco palavras-chave. Marque a alternativa correta. A) Try, catch, throw, throws e finally. B) Try, catch, class, final e finally. C) Try, catch, switch-case, throw e finally. D) Void, throw, throws, static e abstract. E) Private, public, static, protected e void. 3) Analise o código a seguir e marque a alternativa incorreta. try { //bloco de código cujos erros estão sendo monitorados } catch(TipoExceç1 obEx){ //tratador de TipoExceç1 } catch(TipoExceç2 obEx){ //tratador de TipoExceç2 } A) O código é referente a um tratamento de exceção utilizando try-catch. B) No código, o try é responsável por monitorar a exceção, que pode ser qualquer implementação. C) As palavras try-catch formam a base do tratamento de exceções. D) No código temos dois catch associados a um único try. E) Caso uma exceção fosse lançada, ela seria capturada pela instrução try. 4) Quais são as consequências de uma exceção não capturada? A) O programa apenas ignora a instrução catch. B) O programa terminará normalmente. C) Não teremos problemas caso o programa passe uma mensagem através de um método print para o usuário. D) O programa não terminará de forma normal. E) Não teremos necessidade de usar o try-catch. 5) Marque a alternativa incorreta. A) Um dos principais benefícios da exceção é que seu programa não pare a execução. B) As divisões por zero ocorrem no erro "ArithmeticException". C) Quando extrapolamos o limite de um Array ocorre um erro "ArrayIndexOutOfBoundsException". D) Blocos try podem ser aninhados. E) Caso tenhamos um try dentro de outro, o interno não necessita ter uma instrução catch associada. NA PRÁTICA Toda aplicação está suscetível a erros, e estes erros podem acontecer com uma frequência mais comum do que se pensa. Para exemplificarmos erros que podem ocorrer na aplicação, podemos citar os seguintes: tentar abrir um arquivo inexistente, manipular um tipo de dado como se fosse outro tipo, fazer uma divisão por zero, manipular um objeto com valor nulo, tentar utilizar métodos ou classes não existentes, tentar conectar a um servidor ou banco de dados inexistente, entre outros. Esseserros são chamados de exceções e devem ser tratados pelo programador para controlar tais imprevistos. Para tratar as exceções em java, são utilizados os comandos try catch. O try catch funciona da seguinte maneira: o código que você quer monitorar fica dentro do bloco do try; caso aconteça alguma exceção, o catch captura e trata. SAIBA MAIS Para ampliar o seu conhecimento a respeito desse assunto, veja abaixo as sugestões do professor: Aula de Java 037 - try catch, tratamento de erros Assista e vídeo e saiba mais sobre como tratar possíveis erros em Java. Conteúdo interativo disponível na plataforma de ensino! Try, Catch e Exemplos: Tratamento de Erros – Parte 1 No artigo abaixo você saberá mais sobre o tratamento de erros com os blocos Try e Catch, em C#. Conteúdo interativo disponível na plataforma de ensino! Blocos Try/Catch O artigo abaixo artigo apresenta informações sobre programação utilizando os blocos Try/Catch no Java. Conteúdo interativo disponível na plataforma de ensino!
Compartilhar