A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

“Nature provides exceptions to every rule.“

Apresentações semelhantes


Apresentação em tema: "“Nature provides exceptions to every rule.“"— Transcrição da apresentação:

1 “Nature provides exceptions to every rule.“
4 – Exceções “Nature provides exceptions to every rule.“ - Margaret Fuller

2 “Nosso software não tem bugs.”
“Nós não encontramos bugs em nosso software.” Entradas (as vezes maliciosa), falhas na Rede, falhas no Banco de Dados... Tratamento de erros e exceções A afirmação “Nosso software não tem bugs.” é bastante pesada, e creio que a maioria dos desenvolvedores software que são mais experientes não diriam isso. Talvez uma afirmação mais cautelosa seria “Nós não encontramos bugs em nosso software.” Muito provavelmente é isto que uma pessoa queria dizer quando ela diz que seu software não tem bug. (mas isso é um papo mais intimamente relacionado com testes de software, que de certo modo tem a ver com o assunto da aula de hoje) O que pode acontecer é que até aquele momento nosso software não foi submetido a uma determinada entrada com potencial de realçar algum componente defeituoso de nosso programa. Não apenas entradas específicas, mas situações que poderiam impedir nosso programa de funcionar corretamente. Ex (entrada maliciosa): SQLInject Ex (clássico).: falha de rede Por estes motivos o tratamento de erros e exceções é comumente uma prática adotada em todas as empresas de desenvolvimento de software, com o objetivo de entregar produtos robustos e com qualidade a seus clientes.

3 Contextualização Implementação do programa que executa nos caixas de auto-atendimento dos bancos.

4 Motivação O que acontece com o método saca(1000)?
Voltando ao exemplo da Conta Corrente. O que aconteceria com o método saca(1000)? Bem, depende de como ele foi implementado. Mas, um detalhe em que todos nós concordamos é que o método saca é um método “crítico”, um método perigoso. Precisamos sempre checar se o cliente será realmente capaz de sacar o que pede, ou seja, se ele tem saldo disponível para tal. A solução mais simples utilizada antigamente é a de marcar o retorno de um método como boolean e retornar true, se tudo ocorreu da maneira planejada, oufalse, caso contrário, como está no código acima. E aí, teríamos que fazer um texte (if) quando formor sacar para verificar se tudo ocorreu direitinho.

5 Algum problema nisso? Como saber se o usuário passou um valor <0?
Qual seria o problema dessa solução? Repare que tivemos de lembrar de testar o retorno do método, mas não somos obrigados a fazer isso. Esquecer de testar o retorno desse método teria consequências drásticas: a máquina de autoatendimento poderia vir a liberar a quantia desejada de dinheiro, mesmo que o sistema não tivesse conseguido efetuar o método saca com sucesso, como no exemplo a seguir. Mesmo invocando o método e tratando o retorno de maneira correta, o que faríamos se fosse necessário sinalizar quando o usuário passou um valor negativo como quantidade? Uma solução seria alterar o retorno de boolean para int e retornar o código do erro que ocorreu. Isso é considerado uma má prática (conhecida também como uso de "magic numbers"). A documentação fica extensa e o código não fica legível. Vamos evitar a Programação Orientada a Gambiarras. Como saber se o usuário passou um valor <0? Magic numbers: mudar o retorno de boolean para int, e tratar cada número como código de um erro que ocorreu. Nós perdemos o retorno do método e o valor devolvido é "mágico" e só legível perante extensa documentação; Continuamos não obrigando o programador a tratar esse retorno (ele pode esquecer...) e, caso ele esqueça, seu programa rodará em um estado inconsistente.

6 Exceção Por esses e outros motivos, utilizamos um código diferente em Java para tratar aquilo que chamamos de exceções: os casos onde acontece algo que, normalmente, não iria acontecer. Exemplo: o argumento do saque inválido, além do limite disponível ou um valor negativo Uma exceção representa uma situação que normalmente não ocorre e representa algo de estranho ou inesperado no sistema.

7 Estrutura: blocos try-catch
try { // Insira algum código aqui que possa causar algum // tipo de exceção. // Podemos ter muitas linhas de código aqui // ou apenas uma. } catch (MinhaExcecao ex) { // Insira um código aqui que manipule essa exceção. finally{ // libere os recursos alocados no “try” Adicionalmente, nós também podemos utilizar a cláusula finally. O finally é executado independentemente do lançamento ou não de uma exceção dentro do bloco try. Por isso, é prática comum utilizarmos o finally para liberar os recursos (fechar seus arquivos, liberar sockets, fechar conexão com bancos de dados, etc.) utilizados no bloco try (uma vez que temos certeza que ela irá sempre ser executada. Inclusive, não faz sentido colocar nas cláusulas catch pois senão teríamos que duplicar o código caso houvesse mais de um catch (como vamos mostrar mais adiante). Para todo try devemos ter pelo menos 1 catch ou 1 finally ou ambos. Não faria sentido uma clásula try sem um bloco catch.

8 Execício I Antes de resolvermos o nosso problema, vamos ver como a Java Virtual Machine age ao se deparar com situações inesperadas, como divisão por zero ou acesso a um índice da array que não existe. Para aprendermos os conceitos básicos das exceptions do Java, teste o seguinte código você mesmo (5 minutos) O que é impresso e qual a ordem de execução dos métodos

9 Execício I Main  Metodo1  metodo2
cada método tem suas variáveis locais (só o método em questão enxerga) Toda invocação de método é empilhada na pilha de execução (stack) Repare o método main chamando metodo1 e esse, por sua vez, chamando ometodo2. Cada um desses métodos pode ter suas próprias variáveis locais, isto é: ometodo1 não enxerga as variáveis declaradas dentro do main e por aí em diante. Como o Java (e muitas das outras linguagens) faz isso? Toda invocação de método é empilhada em uma estrutura de dados que isola a área de memória de cada um. Quando um método termina (retorna), ele volta para o método que o invocou. Ele descobre isso através da pilha de execução (stack): basta remover o marcador que está no topo da pilha:

10 Resultado Exceção: índice fora dos limites do array stack trace, ou
Porém, o nosso metodo2 propositadamente possui um enorme problema: está acessando um índice de array indevido para esse caso; o índice estará fora dos limites da array quando chegar em 10! Exceção: índice fora dos limites do array stack trace, ou rastro da pilha

11 Sistema de exceções do Java
Quando uma exceção é lançada (throw), a JVM entra em estado de alerta e vai ver se o método atual toma alguma precaução ao tentar (try) executar esse trecho de código;

12 Sistema de exceções do Java
Quando uma exceção é lançada (throw), a JVM entra em estado de alerta e vai ver se o método atual toma alguma precaução ao tentar (try) executar esse trecho de código; Exceção é lançada no metodo2, mas ele não toma nenhuma precaução (try); JVM, pára a execução dele e desce um stackFrame; A exceção (batata quente) continua viva, pois ninguém tratou ela. Logo, ela é passada adiante. JVM volta pra o metodo1, mas ele também não toma nenhuma precaução com a exceção ArrayIndexOutOfBoundsException; De modo similar, a exceção vai pro main, que também não a trata, e assim o programa explode e pára de funcionar! ArrayIndexOutOfBounds

13 Obviamente, aqui estamos forçando esse caso e não faria sentido tomarmos cuidado com ele. É fácil arrumar um problema desses: basta percorrermos a array no máximo até o seu length. Porém, apenas para entender o controle de fluxo de uma Exception, vamos colocar o código que vai tentar (try) executar o bloco perigoso e, caso o problema seja do tipo ArrayIndexOutOfBoundsException, ele será pego (caught). Repare que é interessante que cada exceção no Java tenha um tipo... ela pode ter atributos e métodos.

14 ?

15 Retire o try/catch e coloque ele em volta da chamada do metodo2.
?

16 Faça o mesmo, retirando o try catch novamente e colocando em volta da chamada do metodo1. Rode os códigos, o que acontece? ? A partir do momento que uma exception foi catched (pega, tratada, handled), a execução volta ao normal a partir daquele ponto.

17 Errors Unchecked exceptions Checked exceptions Hierarquia Geralmente são causadas por indisponibilidades ou inexistência do recurso Geralmente são causadas por erro de implementação Situações incomuns que não são causados por erro de implementação Erros são lançados (são throwable) mas são eventos que não precisamos manipular, pois está fora de nossa alçada. Um código que gera erros é compilado sem problemas. Tecnicamente, os erros não são exceções, não derivam de Exception. ClassCastException seria um RuntimeException ou um checked Exception.

18 NullPointerException e ClassCastException, são checked (obrigatoriamente precisam ser tratadas) ou unchecked / runtime? São unchecked. Pois são causadas por erros de programação, ou seja, poderíamos consertar a implementação do nosso código de modo que tais exceções não sejam mais lançadas (pelo menos a partir do trecho de código específico que foi tratado).

19 Unchecked/RuntimeExceptions
número/0  ArithmeticException acessar elemento fora dos limites de um array  ArrayIndexOutOfBoundsException acessar atributos ou chamar métodos de referência nula  NullPointerException Tentar converter uma variável de referência em um tipo que não passa no teste É-UM (instanceof)  ClassCastException Também são chamadas de Unchecked Exceptions Podem ser consertadas programaticamente As runtime exceptions são todas aquelas exceções que poderiam ser evitadas por nós programadores. É possível checar se o denominador da expressão é 0, ou checar se o índice para acessar o array está dentro dos limites do mesmo ou ainda, checar se uma referência é nula. Por esse motivo, a JVM não nos obriga a usar o try-catch nessas situações, e também chamamos essas exceções de unchecked.

20 Unchecked/RuntimeExceptions

21 Unchecked/RuntimeExceptions

22 Checked Exceptions obriga a quem chama o método ou construtor (que lança a exceção) a tratar essa exceção checked: o compilador checará se ela está sendo devidamente tratada, diferente das anteriores, conhecidas como unchecked caso não esteja sendo tratada, o código não compilará Compila?

23 Como resolver? 1 2 No início, existe uma grande tentação de sempre passar o problema pra frente para outros o tratarem. Pode ser que faça sentido, dependendo do caso, mas não até o main, por exemplo. Acontece que quem tenta abrir um arquivo sabe como lidar com um problema na leitura. Quem chamou um método no começo do programa pode não saber ou, pior ainda, tentar abrir cinco arquivos diferentes e não saber qual deles teve um problema! Não há uma regra para decidir em que momento do seu programa você vai tratar determinada exceção. Isso vai depender de em que ponto você tem condições de tomar uma decisão em relação àquele erro. Enquanto não for o momento, você provavelmente vai preferir delegar a responsabilidade para o método que te invocou.

24 Múltiplas exceções 1 2 É desnecessário declarar no throws as exceptions que são unchecked, porém é permitido e às vezes, facilita a leitura e a documentação do seu código. 3

25 Lançando exceções throw está no imperativo, ou seja, significa lance
IllegalArgumentException diz um pouco mais: algo foi passado como argumento e seu método não gostou. Ela é uma Exception unchecked pois estende de RuntimeException e já faz parte da biblioteca do java. (IllegalArgumentException é a melhor escolha quando um argumento sempre é inválido como, por exemplo, números negativos, referências nulas, etc). algo foi usado como argumento e o método saca não gostou RuntimeException é muito genérica

26 Lançando exceções É boa prática adicionar msg explicando a exceção
E se o valor passado fosse negativo, como resolveríamos esse problema?

27 O que colocar dentro do try?

28 O que colocar dentro do try?
1 Mas há ainda uma outra opção: imagine que, para o nosso sistema, uma falha ao sacar da conta poupança deve parar o processo de saques e nem tentar sacar da conta corrente.  2

29 Criando nossa própria Exceção

30 Discussão final Existe uma péssima prática de programação em java que é a de escrever o catch e o throws com Exception. Existem códigos que sempre usam Exception pois isso cuida de todos os possíveis erros. O maior problema disso é generalizar o erro. Se alguém joga algo do tipo Exception para quem o chamou, quem recebe não sabe qual o tipo específico de erro ocorreu e não vai saber como tratar o mesmo. Sim, há casos onde o tratamento de mais de uma exception pode ser feito de uma mesma maneira. Por exemplo, se queremos terminar a aplicação tanto no caso de IOException quanto em SQLException. Se fizermos catch(Exception e)para pegar esses dois casos, teremos um problema: a aplicação vai parar mesmo que outra exceção seja lançada. A solução correta seria ter dois catches, mas aí teríamos código repetido. Para evitar o código repetido, podemos usar o multi-catch do Java 7, que permite um mesmo catch cuidar de mais de 1 exceção, através da sintaxe:  catch(IOException | SQLException e) { ... } .

31 Referências Essa aula utilizou os exemplos das apostilas caelum e do livro de certificação Java (SCJP por Kathy Sierra). Leitura adicional:


Carregar ppt "“Nature provides exceptions to every rule.“"

Apresentações semelhantes


Anúncios Google