Baixe o app para aproveitar ainda mais
Prévia do material em texto
Linguagem de Programação Visual QI ESCOLAS E FACULDADES Curso Técnico em Informática Unidade 5 – Tratamento de exceções QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 2 SUMÁRIO INTRODUÇÃO ............................................................................................................... 3 ERROS E FALHAS .................................................................................................................. 3 CLASSES DE EXCEÇÕES ......................................................................................................... 4 BLOCOS TRATADORES DE EXCEÇÃO .......................................................................................... 6 Sintaxe ............................................................................................................................... 6 Exemplo ............................................................................................................................. 7 LANÇAMENTO DE EXCEÇÕES ................................................................................................... 8 RESUMO .................................................................................................................... 10 EXEMPLO PRÁTICO ................................................................................................... 10 TRATANDO A EXCEÇÃO NA ORIGEM ......................................................................................... 12 LANÇANDO UMA EXCEÇÃO..................................................................................................... 13 BIBLIOGRAFIA ........................................................................................................... 14 QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 3 INTRODUÇÃO Quero iniciar esta aula fazendo uma pergunta provocativa: Existem programas sem erro? E sem falhas? Afinal erro e falha não seria a mesma coisa? Só nestas três linhas já teríamos assunto para aulas e mais aulas sobre a matéria, porém nossa disciplina não é sobre teste de software muito menos sobre teorias de engenharia de software, porém as mesmas são totalmente pertinentes ao nosso contexto. Respondendo as duas primeiras perguntas em uma só palavra: Não. Não existem programas 100% sem erros, pois os erros fazem parte do processo de desenvolvimento, visto que somos humanos e sujeitos a errar, e mapear e resolver todos os erros tomaria muito tempo e recursos, às vezes inviabilizando a produção de um programa. Então programas são produzidos e lançados com um nível aceitável de erros, conhecidos ou não. Temos uma infinidade de exemplos desta afirmação no mercado de software, tenha visto a enorme quantidade de services packs e atualizações de sistemas. Erros e falhas Erro é todo comportamento anômalo e que não foi previsto durante o desenvolvimento, que acarreta uma parada ou mau funcionamento na execução do sistema. E a tal da falha? Falha é um erro em potencial, ou seja, que pode ocorrer durante a execução de um sistema, mas que ainda não se manifestou ou ocorreu. As falhas são na sua maioria previsíveis e mapeadas. Para as falhas mapeadas os sistemas usam de recursos para o tratamento das mesmas. Ou seja, um bom sistema é aquele que é tolerante a falhas, que consegue perceber, tratar e dar um resultado eficiente à mesma, sem com isto interromper a execução de sistema, ou caso seja necessária a interrupção da execução, fazê-la de maneira segura e controlada. Um exemplo simples de falha pode ser um caso de uma transmissão de dados via rede e esta rede ter uma “queda”. Isto gerará uma falha no processo de transmissão e, caso esta falha não seja tratada, ocorrerá um erro e consequentemente o encerramento da execução do programa. Informações com QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 4 formato/tipo errado, apontamentos para objetos inválidos e/ou nulos também são falhas comuns em programas. Então há um consenso de que caso não se trate uma falha teremos um erro e que este tratamento é uma boa prática. Agora falta saber como podemos fazer isto dentro de nossos códigos Java. Classes de Exceções As falhas que podem ocorrer dentro de um sistema são chamadas de exceções. Uma exceção em Java é um objeto. A classe pai de todas as exceções é a Throwable. A partir dela, temos uma hierarquia de classes de Exeptions, que pode ser vista através da figura 1: QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 5 Figura 11 Se observarmos, temos duas importantes divisões no esquema acima, IOException e RuntimeException. Existem diversas “famílias” de Exceptions, cada qual especializada para controlar e notificar um tipo diferente de falha, de maneira mais genérica, como falhas de IO (entrada e saída) e falhas de execução (runtime), 1(HORSTMAN, 2008, pág. 456). QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 6 especializações com a determinação de arquivo não encontrado e índice do array fora do escopo. Um exemplo disso é quando trabalhamos com arrays e eventualmente utilizamos um índice além do seu tamanho. Isto é uma falha, que lança a exceção ArrayIndexOutOfBounds e, se não tratada, encerra a execução do programa (runtime error – erro em tempo de execução). Blocos tratadores de exceção No Java se utiliza o controle de falhas através de blocos de código, o famoso bloco try – catch – finally. Para aqueles que conhecem a língua inglesa já percebeu a ideia (tente – capture – finalmente/for fim). Então dentro de um programa Java sempre que exista a possibilidade de uma falha ocorrer (falha já prevista ou mapeada – logo falaremos da diferença entre elas) usamos um bloco 'try { }' e colocamos o trecho “perigoso” dentro dele. Um bloco try sempre deve ser acompanhado de um ou mais blocos catch e/ou um bloco finally. Vamos entender: indica-se um bloco de código com possibilidade de ocorrência de falha com a diretiva try; após este bloco colocamos um ou mais blocos catch, para a captura das possíveis falhas (que no Java são chamadas de Exception – Exceções) – um catch para cada exceção possível – e um bloco finally com instruções que devam ser executadas de qualquer maneira, ocorrendo ou não uma falha/exceção. Sintaxe try { //instruções } catch (Exceção e1) { //instruções } catch (Exceção e2) { //instruções } finally { //instruções } QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 7 Exemplo Observando o código acima vemos que as operações de divisão e atribuição nas variáveis estão dentro de um bloco try, onde haverá por parte da máquina virtual o tratamento de falhas. Como sabemos divisão de valores por zero resultam em uma impossibilidade matemática*, portanto causará uma falha, que se não tratada resultará em um erro. Por isto logo após o bloco try colocamos um bloco catch, onde será testada a ocorrência de uma exceção aritmética (ArithmeticException). Caso ela ocorra – no nosso exemplo sempre ocorrerá, pois a variável b sempre valerá 0), o programa apresentará no terminal a mensagem de “divisão por zero”. Como ocorreu a exceção,logo após a apresentação da mensagem no terminal, o programa passará a executar o bloco finally (caso ele exista), e nesse caso, apresentará as mensagens com os valores das variáveis 'd' e 'e'. Suponhamos que agora a variável 'b' seja declarada da seguinte forma: int b = 2; Neste caso será possível realizar a primeira operação de divisão sem a ocorrência de falha aritmética. Porém se ler atentamente o código, verás que a QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 8 segunda divisão não será possível, pois a variável 'c' é do tipo Integer, ou seja, um objeto da classe Integer. que recebeu um valor null. Então ao tentar a divisão a máquina virtual não conseguirá acessar o valor para o divisor, pois este é nulo, disparando uma NullPointerException (exceção de ponteiro nulo). No código podemos ver um segundo bloco catch, com a captura da ocorrência desta exceção. Importante destacar que, caso o primeiro comando dentro do bloco try gere uma exceção, os demais comandos dentro do bloco não serão executados. *Nota: No Java uma divisão por zero só causa uma exceção caso a operação seja feita com inteiros. Por conta dos mecanismos de cálculo e armazenamento de valores com ponto flutuante, uma divisão por zero em tipos float e double resultam em um valor infinito (infinity). Lançamento de exceções Vimos que falhas podem ocorrer por problemas da codificação e não previsão de um ou mais ocorrências, porém em muitos casos sabemos desta possibilidade e temos que avisar outras partes do código que falhas podem ocorrer ao se executar determinando método. Ou seja, podemos avisar ao programa da possibilidade de uma falha e obrigar ele a criar mecanismos de controle (esta será uma falha mapeada). Para isto podemos “lançar” (throws) exceções para os “chamadores” do método. Qualquer exceção é um objeto de uma classe especializada da Exception, que por sua vez é uma especialização da classe Throwable. Podemos criar exceções personalizadas, bastando para isto “estender” a classe Throwable, mas isto não será foco de nossas aulas. Já sabemos que podemos e devemos tratar as falhas, mas agora vem uma segunda pergunta: Onde é que devo tratar estas falhas? Depende! Sabemos que toda e qualquer instrução a ser executada pelos programas Java devem estar dentro de um método (salvo algumas exceções). Então, se ocorrerem falhas, elas ocorrerão sempre dentro de um método, quando de sua invocação (chamada e execução). Agora voltamos à resposta da pergunta anterior. Podemos tratar a falha dentro do método que a origina, usando para isto os blocos try – catch – finally e QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 9 “resolvendo o problema ali mesmo”. Mas também podemos somente sinalizar que uma falha ocorreu e passarmos esta informação para o método que o invocou e deixando para este método (o invocador) a responsabilidade de tratar a falha. Para isto usamos a “palavra reservada” throws junto à declaração do método/classe, seguida da Classe de Exception que o mesmo “lançará” para seu chamador. Observe o exemplo: public void meuMetodo(int a, int b, Integer c) throws ArithmeticException, NullPointerException { double d; double e; d = a / b; e = a / c; } Neste exemplo estamos realizando as mesmas operações do exemplo anterior, que sabemos ter falhas. No exemplo atual, passamos a responsabilidade de tratar as falhas para os métodos que invocarem meuMetodo(). Na assinatura deste método estamos explicitando que as exceções ArithmeticException e NullPointerExcetion, se ocorrerem, serão lançadas adiante e devem ser tratadas pelo “chamador”. Um detalhe importante é que é possível ir lançando exceções “para cima” até chegarmos ao primeiro método, o main, e somente neste tratar as falhas (é possível, mas nem um pouco aconselhável). Também há a possibilidades de que se tratem algumas das exceções dentro do método ao passo que se lance outras para os “chamadores”. Ou seja, a cada camada podemos tratar um tipo de falha. Veja o exemplo: Figura 2 Neste caso a falha por objeto nulo é tratada dentro do método e, em caso de ocorrência, a variável “e” recebe o valor de “a”. Já no caso de uma falha aritmética a exceção será lançada para o chamador do método. QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 10 É muito importante ficarmos atentos ao uso dos try-catch-finally e aos comandos que colocamos dentro dos mesmos, pois a ocorrência de uma exceção anula a execução dos comandos subsequentes dentro do bloco try. Algumas vezes é necessário que usemos diversos blocos try-catch-finally encadeados ou em sequência para que tenhamos o comportamento desejado quando da execução com ou sem falhas. Também é importante salientar que para o tratamento de falhas o bloco try é obrigatório, seguido de um ou mais blocos catch e/ou um bloco finally. Ou seja, sempre teremos um bloco try “cercando” a possibilidade de uma ou mais falhas, e dependendo da necessidade este bloco será seguido de blocos catch para tratar cada um dos tipos de exceções possíveis, ou somente bloco finally, ou ainda os blocos catch mais o finally. É possível criar classes de exceções personalizadas para nossa aplicação. Estas classes serão especializações (extends) da classe Exception ou suas 'filhas'. Não é objeto desta apostila se aprofundar neste assunto, mas depois de atingido um entendimento mais aprofundado do uso do tratamento de falhas, esta prática irá se tornar muito interessante e produtiva. RESUMO Sistemas tendem a conter falhas. Estas falhas, caso não tratadas, resultarão em erros e encerramento da execução do programa. Para realizarmos o tratamento destas falhas usamos de blocos de try-catch-finally e de objetos das classes Throwable e Exception e suas especializações. A boa aplicação destas técnicas nos garantirão sistemas mais tolerantes a falhas ou que, ao menos, consigam reagir de maneira adequada a suas ocorrências. De agora em diante muito dos conteúdos a serem trabalhados necessitarão de tratamento de exceções, o que nos garantirá uma prática maior no uso da técnica. Mas antes aproveite os exercícios propostos para entender e fixar melhor o conteúdo. EXEMPLO PRÁTICO Vamos analisar um exemplo prático, e veremos neste exemplo as possibilidades de tratamento de exceções. QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 11 Nosso exemplo será baseado em uma classe “Operacao” que tem como atributos o “valor1” e o “valor2”, ambos inteiros, um construtor e um método que retorna a divisão do valor1 pelo valor2. Figura 3 - classe Operacao Vamos montar agora a classe TesteOperacao, onde solicitaremos ao usuário que informe dois valores inteiros utilizando JOptionPane, em seguida chame a operação “dividir” e exiba o resultado. Figura 4 – Classe TesteOperacao Agora vamos restar o programa. Na classe TesteOperacao, utilizamos o atalho Shift+F6. O programa executa e apresenta a primeira janela, solicitando um número inteiro. No exemplo da figura 5, informamos o valor 5. QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 12 Figura 5 Após pressionarmos Ok, vemos a segunda janela, onde digitamos o valor 0, conforme mostra a figura 6: Figura 6 Ao pressionarmos Ok, vemos na parte inferior dajanela do Netbeans que ocorreu um erro (vide figura 7). Figura 7 O erro em questão é o ArithmeticException – divisão por zero. Isso aconteceu porque o sistema não previu esta falha. Vamos observar de que formas isto pode ser corrigido. Tratando a exceção na origem Tratar na origem significa circundar o comando que pode gerar um erro com um bloco try. Como o método deve retornar um número inteiro, alteramos o método para que caso haja a exceção aritmética, ele não calcula a divisão e armazena o valor 0, retornando o valor da variável “res” em qualquer situação. QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 13 Figura 8 Assim, executando o programa novamente, e inserindo os mesmo valores nas caixas (5 e 0), o programa nos apresenta o resultado 0: Figura 9 Certo, evitamos o erro, porém, a resposta está correta? O certo não seria apresentar para o usuário uma mensagem informando que a operação não é possível, ao invés de simplesmente mostrar 0? Lançando uma exceção Vamos então alterar o nosso código, que ao invés de tratar a exceção na origem, vamos lançar esta exceção através do mecanismo throws para que seja tratada pelo “chamador”. Primeiramente vamos alterar o método dividir, adicionando o mecanismo throws (que indica que a exceção, se ocorrer, deve ser tratada quando o método for chamado): QI ESCOLAS E FACULDADES CURSO TÉCNICO EM INFORMÁTICA L IN G U A G E M D E P R O G R A M A Ç Ã O V IS U A L Unidade 5 - Tratamento de exceções Pág. 14 Figura 10 Agora, vamos alterar a classe TesteOperacao para tratar o possível erro: Figura 11 Assim, se executarmos o programa informando os mesmos valores (5 e 0), temos agora uma mensagem de erro: Figura 12 Dica: faça agora um teste: rode o programa, e quando ele solicitar o primeiro valor experimento digitar um texto ou deixar em branco... BIBLIOGRAFIA HORSTMANN, Cay. Conceitos de Computação em Java. 5ª edição. Porto Alegre: Bookman, 2008. LOPES, Camilo. Tratamento de exceções. Imasters, 2009. Disponível em http://imasters.com.br/artigo/11669/java/tratamento_de_excecoes/. http://imasters.com.br/artigo/11669/java/tratamento_de_excecoes/
Compartilhar