O documento discute erros e casos excepcionais em Java, incluindo conceitos, representação, criação, detecção e tratamento. Aborda exceções Java, asserções Java e boas práticas, incluindo segurança.
4. Representação e criação Em Java, casos excepcionais, erros de programação e erros no ambiente de execução representam-se através de lançáveis Os lançáveis são criados e lançados Explicitamente: throw Implicitamente: assert Automaticamente: JVM, por exemplo Por métodos sobre os quais não temos controlo 2009/2010 Programação Orientada por Objectos 4
5. Detecção e tratamento Lançáveis em Java podem ser capturados Para lidar integralmente com um caso excepcional Para lidar parcialmente com um caso excepcional Apenas para “arrumar a casa” , quando não se sabe lidar com um caso excepcional Para terminar o programa de forma adequada em caso de erro de programação ou de erro no ambiente de execução 2009/2010 Programação Orientada por Objectos 5 Isto não é uma recuperação, mas sim um elegante harakiri.
6. Lançáveis Java Usados para representar Casos excepcionais Erros de programação Erros no contexto de execução de um programa São objectos de classes pertencentes à hierarquia com base na classe Throwable São lançáveis através da instrução throw Lançamento interrompe o fluxo normal de um programa Programação Orientada por Objectos 2009/2010 6
7. Hierarquia de lançáveis em Java 2009/2010 Programação Orientada por Objectos 7 Throwable Casos excepcionais. Erros de programação correspondentes a violação de pré-condições em contratos não privados. Erros no ambiente de execução. Error Exception IOException VirtualMachineError … … RuntimeException AssertionError ArithmeticException Erros de programação (excepto violação de pré-condições em contratos não privados). NullPointerException …
8. Hierarquia de lançáveis em Java Throwable Error VirtualMachineError … AssertionError Exception IOException … RuntimeException ArithmeticException NullPointerException IndexOutOfBoundsException … Erros de programação (excepto violação de pré-condições em contratos não privados). Criação implícita quando asserção falha. Normalmente irrecuperáveis. Erros de programação correspondentes a violações pré-condições de contratos não privados. Criação explícita. Lançamento com throw. Normalmente irrecuperáveis. 2009/2010 8 Programação Orientada por Objectos Erros no ambiente de execução. Criação automática. Normalmente irrecuperáveis. Casos excepcionais. Criação explícita. Lançamento com throw. Normalmente recuperáveis.
9. Características 2009/2010 Programação Orientada por Objectos 9 Possibilidade de lançamento tem de ser declarada! 1 Para aplicações não críticas. 2 Excepto RuntimeException e derivadas. 3 Para violações de pré-condições em contratos não privados. 4 Para todos os restantes casos. 5 Excepto AssertionError.
12. Não recomendada para restantes casos (Error e RuntimeException).2009/2010 11 Programação Orientada por Objectos
13. Lançamento explícito para erro de programação static public double squareRoot(final double value) { if (value < 0.0) throw new IllegalArgumentException( "Illegal value " + value + ", should be 0 ≤ value"); … } 2009/2010 12 Programação Orientada por Objectos Violação de pré-condição em contrato não privado.
14. Delegação ou declaração de passagem (throws) public void someMethod(…) throws SomeException { … anObject.someOtherMethod(…); … // only if no exception is thrown. } 2009/2010 Programação Orientada por Objectos 13
15. Lidando com caso excepcional public void someMethod(…) { try { … anObject.someOtherMethod(…); … // only if no exception is thrown. } catch (final SomeException exception) { … // fix the problem using information available. } … // continue execution. } 2009/2010 14 Programação Orientada por Objectos
16. Arrumando a casa com finally public void someMethod(…) { try { … anObject.someOtherMethod(…); … } catch (final SomeException exception) { … } finally { … // clean house in any case. } … } 2009/2010 15 Programação Orientada por Objectos Bloco finally executado mesmo no caso de excepções não capturadas, retornos, novos lançamentos, asserções falhadas, etc.
17. Lidando parcialmente com caso excepcional public void someMethod(…) throws SomeException { try { … anObject.someOtherMethod(…); … } catch (final SomeException exception) { … // fix part of the problem using information available. throw exception; } … } 2009/2010 16 Programação Orientada por Objectos Relançamento da excepção capturada.
18. Informação adicional sobre a ocorrência public void someMethod(…) throws SomeOtherException { try { … anObject.someOtherMethod(…); … } catch (final SomeException exception) { … // clean house if necessary. throw new SomeOtherException( "Informative message", exception); } … } 2009/2010 17 Programação Orientada por Objectos Apenas se se tratar de um caso excepcional. Lançável capturado é a causa do novo lançável.
19. Captura múltipla public void someMethod(…) { try { … } catch (final SomeException exception){ … } catch (final RuntimeException exception){ … } catch (final IOException exception){ … } catch (final Exception exception){ … } … } Excepções mais específicas têm de estar primeiro. 2009/2010 18 Programação Orientada por Objectos
20. Operação printStackTrace publicvoidsomeMethod(…) { … try { … } catch (final SomeExceptionexception) { exception.printStackTrace(); … } … } Imprime uma representação da pilha de invocações no momento em que a excepção foi lançada. pt.iscte.dcti.poo.exceptions.SomeException atpt.iscte.dcti.poo.SomeClass.someMethod(SomeClass.java:16) atpt.iscte.dcti.poo.SomeOtherClass.someOtherMethod(SomeOtherClass.java:9) atpt.iscte.dcti.poo.MainClass.main(MainClass.java:36) 2009/2010 19 Programação Orientada por Objectos
21. Contratos: documentação e verificação /** * Returns the double closest to the square root of its argument * value. * * @pre 0 ≤ value * @post … * @param value the value whose square root will be approximated * @throws IllegalArgumentException If value < 0 */ static public double squareRoot(final double value) { if(value < 0) throw new IllegalArgumentException(“Message"); … assert … : "Informative message"; return result; } 2009/2010 20 Programação Orientada por Objectos As asserções, por omissão, estão desactivadas. Para que tenham algum efeito tem de se executar a JVM com a opção -ea.
22. Invariante de instância public Rational(final int numerator, final int denominator) { if(denominator == 0) throw new IllegalArgumentException("Message"); this.numerator = numerator; this.denominator = denominator; normalize(); checkInvariant(); } private void checkInvariant() { assert 0 < denominator : "…"; assert gcd(numerator, denominator) == 1 : "…"; } … Onde? No final dos construtores, no início de métodos não modificadores e no início e no fim de métodos modificadores. O invariante de instância é a condição que todas as instâncias de uma classe têm de verificar para que estejam num estado correcto. 2009/2010 21 Programação Orientada por Objectos
23. Métodos privados private void reduce() { assert denominator != 0; if (denominator < 0) { denominator = -denominator; numerator = -numerator; } final intgcd = gcd(numerator, denominator); numerator /= gcd; denominator /= gcd; assert mdc(numerator, denominator) == 1 : "…"; assert 0 < denominator : "…"; } 2009/2010 Programação Orientada por Objectos 22 Pré-condição de método privado (parte da implementação da classe) verificada com asserção. Nos métodos privados não se verifica o invariante de instância, pelo menos enquanto tal.
24. Lançáveis definidos pelo programador public class SomeException extends Exception { public Exception() { } public Exception(final String message) { super(message); } public Exception(final String message, final Throwable cause) { super(message, cause); } public Exception(final Throwable cause) { super(cause); } } 2009/2010 23 Programação Orientada por Objectos
25. Boas práticas Distinga claramente a natureza dos erros e casos excepcionais Lide com cada ocorrência usando os mecanismos adequados (e convencionais) à sua natureza 2009/2010 Programação Orientada por Objectos 24
26. Boas práticas Use assert apenas para erros de programação Pré-condições de métodos privados Pós-condições Invariantes de instância Asserções propriamente ditas Use throw Para erros de programação Pré-condições de métodos não privados Casos excepcionais 2009/2010 25 Programação Orientada por Objectos
27. Boas práticas Não tente recuperar de uma ocorrência sem antes perceber a sua causa Não desactive as asserções durante a operação normal do softwaresenão quando tiverem um impacte negativo significativo sobre o seu desempenho Tente recorrer a lançáveis já existentes na biblioteca padrão do Java 2009/2010 Programação Orientada por Objectos 26
28. Boas práticas Documente possibilidade de lançamento de deRuntimeException (e classes derivadas) quando esse lançamento puder ocorrer devido erros na utilização da interface da operação Lembre-se que pode capturar um lançável e lançar um outro que torne mais claro qual o problema (não deve abusar desta estratégia) 2009/2010 Programação Orientada por Objectos 27
29. Boas práticas: segurança Escreva o seu código de modo a que o lançamento de um lançável num método deixe o programa no mesmo estado em que estava antes da operação correspondente ser invocada Se isso não for possível, escreva o código de modo a, pelo menos, deixar todos os objectos num estado válido 2009/2010 Programação Orientada por Objectos 28
30. Boas práticas: testes Para cada unidade (classe ou conjunto de classes intimamente ligadas) crie um caso de teste JUnit Crie os testes antes mesmo de começar a desenhar a unidade: pensar nos testes ajuda a perceber melhor que interface deve ter a unidade Teste sempre as situações limite e casos especiais (referências nulas, cadeias de caracteres vazias, valores numéricos no limite, etc.) 2009/2010 29 Programação Orientada por Objectos
31. Boas práticas: testes Lembre-se que os testes se devem basear apenas na interface não privada da unidade (testes de caixa preta) Evite alterar a interface não privada quando fizer alterações a uma unidade Se precisar de alterar a interface não privada de uma unidade, actualize todos testes e reveja todos os contratos e respectiva documentação Quando alterar a implementação de uma unidade, reveja o seu invariante e execute todos os seus testes 2009/2010 30 Programação Orientada por Objectos
32. A reter… Detecção e tratamento de ocorrências fundamental para boa programação Princípio subjacente à programação em linguagens como o Java é que quanto mais cedo se detectarem erros, mais fácil é corrigi-los e menor o seu impacte Asserções usam-se para expressar condições que devem ser verdadeiras para que o programa esteja correcto Asserções antecipam detecção de erros de programação e melhoram sua localização 2009/2010 31 Programação Orientada por Objectos
33. A reter… A relação das excepções declaradas com a operação em causa deve ser clara e deve ser documentada Detecção de erro de programação ou de erro no ambiente de execução do programa deve levar sistema, se não crítico, a cometer um elegante harakiri, tão simpático para utilizadores quanto possível Um programa honrado percebe quando falha e extingue-se voluntariamente, não deixando que erros se propaguem 2009/2010 Programação Orientada por Objectos 32
34. A ler para as próximas aulas ... Capítulo 18 do livro: Y. Daniel Liang, Introduction to Java Programming, 7.ª edição, Prentice-Hall, 2008.ISBN: 978-0-13-605966-0 2009/2010 Programação Orientada por Objectos 33
35. Sumário Erros e casos excepcionais Conceitos Excepções Erros de programação Erros no ambiente de execução Representação, criação, detecção e tratamento Excepções Java Asserções Java Boas práticas (incluindo segurança) 2009/2010 Programação Orientada por Objectos 34