Preview only show first 10 pages with watermark. For full document please download

[scjp] Slides - Capitulo 5 - Livro Kathy Sierra

[SCJP] Slides - Capitulo 5 - Livro Kathy Sierra Criado pelo pessoal do grupo de estudos para certificação da PR. Vale a pena conferir

   EMBED


Share

Transcript

Grupo de Estudos - SCJP Controle de Fluxo Exceções Assertivas Eduardo Silva ufpb, junho de 2009 instruções if Formato básico: if (expressãoBooleana) { ...println(“entrou no if”); } if (new Boolean(true) && !ehMentira()) { ...println("no if"); } if (a == b & b > c || c != d && d <= a) { ...println("dentro"); } else e else-if if (nota > 7) { ...println(“maior”); } else { ...println(“não-maior”); } if (peso < 40) { ...println(“vôou”); } else if (peso < 55) { ...println(“magro”); } else if (peso < 65) { ...println(“quase”); } else { ...println(“beleza”); } if true { ...println(“it's true”); } if (a < b) { ...println("um"); } if (c > b) { ...println("dois"); } else { ...println("tres"); } else if (true) { ...println("quatro"); } avisos if (ehVerdade()) if (!ehVerdade()) ...println(“paradoxo”); else  casado com o último if ...println(“pior que é verdade”); int verum = 1, falsum = 0; // inválidos: if (verum) if (verum == true) if (1) if (falsum == false) // válidos: if (verum == 1) if (falsum == 0) if (nota > 7) ...println(“passou”); ...println(“deu beleza”); instrução switch char ch = 'a'; char ch = 'a'; if (ch == 'c') { ...println(“cê”); } else { if (ch == 'b') { ...println(“bê”); } else { if (ch == 'a') { ...println(“á”); } else { ...println(“outra”); } } } switch (ch) { case 'c': ...println(“cê”); break; case 'b': ...println(“bê”); break; case 'b': ...println(“á”); break; default: ...println(“outra”); } + switch long l = 11; switch (l) { }  a expressão do switch só avaliará enums e (valores e variáveis que puderem ser implicitamente convertidos num int) final int x = 0, a = 1, b; b = 2; switch (x) { case a: case b: }  o argumento do case tem que ser uma constante em tempo de compilação (variável literal ou final, expressão constante, incluindo enum) + switch long l = 11; switch (l) { } // possible lost of precision  a expressão do switch só avaliará enums e (valores e variáveis que puderem ser implicitamente convertidos num int) final int x = 0, a = 1, b; b = 2; switch (x) { case a: case b: // constant expression required }  o argumento do case tem que ser uma constante em tempo de compilação (variável literal ou final, expressão constante, incluindo enum) três erros de compilação: byte b = 22; switch (b) { case 22: case (b < 23): break; case 128: break; case 22: } alguns detalhes byte b = 22; switch (b) { case (b < 23): // imcompatible types ...println(“switch só testa igualdade”); break; case 128: // possible lost of precision ...println(“o compilador sabe que 128 não cabe num byte”); break; case 22: // o break é opcional case 22: // duplicate case label ...println(“mesmo valor para dois cases”); } mais alguns switch (new Integer(127)) { case 127 { ...println(“deu beleza?”); } } int x = getNumPositivoMenorQueDez(); switch (x) { case 2: case 4: case 6: case 8: ...println(“é par”); break; default: ...println(“é ímpar”); break; } // passagem completa imprime o que? short s = 12; // --s; switch (s) { case 11: ...print(“11”); default: ...print(“default”); case 13: ...print(“13”); } switch-case-default short s = 12; // --s; switch (s) { case 11: ...print(“11”); default: ...print(“default”); case 13: ...print(“13”); }  imprime “default13”  descomentando a segunda linha do exemplo anterior, seria impresso “11default13”  Ou seja, a instrução default pode não vir no final da instrução switch e funciona como qualquer instrução case na passagem completa while e do-while  while útil quando não se sabe quantas vezes o bloco terá que ser repetido while (expressaoBooleana) { // um mói de coisa }  do-while útil quando se quer executar um bloco ao menos uma vez antes de avaliar a expressão do { // outro mói } while (outraExpressao); // <- detalhe no ponto-e-vírgula for  útil quando se souber o números de vezes que executará as instruções do bloco do loop for (/* inicialização */ ; /* condição */ ; /* iteração */) { // corpo do loop } for (int k = 0, j = 1; k < 10 && j < 10; k++, --j) {} // beleza } ...println(k); // k já não existe mais aqui ...println(j); // cannot find symbol  ecxeto por uma saída forçada, as expressões de iteração e condição serão as últimas a seres executada num loop for saídas forçadas e + break  salto para a 1ª instrução depois do loop return  retornará imediatamente ao método chamador System.exit()  o programa será interrompido, VM será encerrada int i = 0; for(;i<10;) { ++i; // mais coisas aqui } // equivalente a um while for (;;) { ... } // loop infinito for (; false; ) { ... } // unreachable statement for (int a = 1, b = 3; b != 1; System.out.println(b)) { // válido! b -= a; } for aprimorado (for-each) for (declaração : expressão) int x; long x2; Long[] La = {4L, 5, 6l}; long[] la = {7l, 8L, 9}; int[][] dobrado = {{3, 2, 1}, {6, 5, 4}}; String[] ss = {“um”, “dois”, “quatro”}; Animal[] animais = {new Dog(), new Cat()}; for (float y: la); for (long lp: La); for (int[] n: dobrado); for (int n2: dobrado[1]); for (String s: ss); for (Object o: ss); for(Animal a: animais); for(x2: la); for(int x2: dobrado); for(int x3: la); for(Dog d: animais); continue e break continue  próxima iteração do laço (não pode vir fora um loop) break  vai para próxima linha depois do laço for (int in = 0; i < 10; i++) { continue; // loop infinito? } for (int i = 0; i < 10; i++) { if (i & 1 == 0) { continue; } if (i == 8) { break; } ...println(i); } instruções rotuladas  muitas instruções em java podem ser rotuladas, mas isso é mais comum em loops  úteis em loops aninhados  o rótulo precisa estar de acordo com as regras de nomes de variáveis válidos rotulo1: for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { ...println(j); continue rotulo1; } ...println(“ufa”); } ...println(“fim”); + rótulos  as instruções continue e break rotuladas devem ficar dentro do loop que tiver o mesmo rótulo ou o código não será compilado int b = 10; int[] a = new int[4]; 1rotulo: for (int n: a) break 1rotulo; rotulo2: { while (b > 0) { ...println(b--); } continue rotulo2; } manipulação de exceções  produz código eficiente e organizado  mantém código de exceções separado do código “principal'  permite “reutilização” do código de exceção para as diferentes exceções possíveis  exceção significa “condição excepcional” (falha no hardware, exaustão de recursos, erros...)  quando um evento excepcional ocorre, diz-se que uma exceção será lançada  o código responsável por fazer algo com a exceção é chamado de manipulador de exceções try catch  try indica um bloco de código em que poderá ocorrer uma exceção (região protegida)  a cláusula catch associa uma (ou mais) exceção(ões) a um bloco de código que a manipulará  se existirem blocos catch, então eles devem ficar sempre depois do bloco try e nada pode ficar entre eles try { captureArquivoNaRede(); leiaArquivoePreenchaTabela(); } catch (NaoPodeCapturarArquivoNaRede e) { useArquivoLocal(); } finally  o bloco finally será sempre executado, mesmo que nenhuma exceção seja lançada  útil para “executar limpeza “ (fechar arquivos, liberar sockets de rede, etc) void fazAlgo() { try { int a = 10; a /= 0; } catch (ArithmeticException e) { System.out.println("no catch"); return; } finally { System.out.println("no finally"); } } // o que será impresso? try { int a = 10 / 0; } System.out.println(a); try { int b = 10 / 0; } finally { ...println(“finally”); } catch (Exception e) { ...println(“catch”); } System.out.println(b); propagação de exceções class Pilha { public static void main(String[] args) { new Cap5().facaUm(); } void facaUm() { facaDois(); } void facaDois() { int a = 1/0; } fazDois() fazUm() main() } Exception in thread "main" java.lang.ArithmeticException: / by zero at Cap5.facaDois(Cap5.java:11) at Cap5.facaUm(Cap5.java:8) at Cap5.main(Cap5.java:5) hierarquia de exceções  as exceções são sempre subclasses de java.lang.Exception  há duas subclasses que derivam de Throwable: Exception e Error  os aplicativos geralmente não conseguem se recuperar de um erro, então mesmo que seu código não os manipule, ele ainda será compilado  a classe Throwable fornece o método printStackTrace() para exibir o rastreamento de pilha do local onde a exceção ocorreu  os tipos RunTimeException, Exception, Error e Throwable podem ser lançados com o uso da palavra throw e podem ser capturados (embora raramente seja capturado algo que não seja um subtipo de Exception) Error Object Throwable Exception RunTimeException correspondência de exceções  os manipuladores de exceções mais específicos devem sempre ser inseridos acima dos de exceções gerais  se uma classe Exception não for o subtipo ou supertipo da outra, a ordem na qual as cláusulas catch serão inseridas não importará try { RandomAccessFile raf = new RandomAccessFile("myfile.txt", "r"); byte[] b = new byte[1000]; raf.readFully(b, 0, 1000); } catch (FileNotFoundException e) { System.out.println("file not found"); } catch (IOException e) { System.out.println("IO Error"); } declarando exceções  uma exceção é dita “verificada” se não é do tipo RunTimeException  as exceções verificadas que um método pode lançar devem ser declaradas, mesmo que ele lance de maneira indireta  utiliza-se a palavra-chave throws na assinatura do método para declarar que o método lança uma dada exceção  quando um método declara que lança uma exceção, não significa que ele sempre o fará, mas sim que ele pode fazê-lo void doStuff() { doMore(); } void doMore() { throw new IOException(); } // dois erros aqui + exceções public static void main(String[] args) { try { new Cap5().fazUm(); } catch (IOException e) {} // IOException is never thrown in body // of corresponding try statement } void fazUm() { fazDois(); } void fazDois() { try { throw new IOException(); } catch (IOException rte) { rte.printStackTrace(); } } ainda + exceções public static void main(String[] args) { new Cap5().fazUm(); } void fazUm() { try { throw new Error(); } catch (Error e) { throw e; } void fazUm() { } try { throw new IOException(); } catch (IOException e) { throw e; } exceções e erros lançados pelo JVM  NullPointerException class NPE { static String s; public static void main(String[] args) { System.out.println(s.length()); } }  StackOverflowError void recursivo() { recursivo() } exceções & erros lançados programaticamente  “programaticamente” = criado por um aplicativo e/ou por um desenvolvedor de API // uma possível implementação do parseInt() de Integer: int parseInt(String s) throws NumberFormatException { boolean parseSuccess = false; int resulta = 0; // parsing complicado aqui if (!parseSuccess) { throw new NumberFormatException(); } return result; }  AssertionError também é lançado programaticamente Os dez erros e exceções principais  ArrayIndexOfBoundsException: lançada ao se tentar acessar um array com um valor de índice inválido int[] a = new int[10]; a[a.length] = 0;  ClassCastException: lançada ao se tentar converter uma variável de referência em um tipo que não passa no teste é-um Object o = new Integer(0); System.out.println((String)o);  IllegalArgumentException: lançada quando um método recebe um argumento formatado de forma diferente do que o método espera - lançado programaticamente Os dez erros e exceções principais  IllegalStateException: quando o estado do ambiente não bate com a operação sendo tentada, p.ex., usando-se um Scanner que já foi fechado. - lançada programaticamente  NullPointerException - lançada pela JVM  NumberFormatException: lançada quando um método que converte uma String em um número recebe uma String que não consegue converter. - lançada programaticamente String s = "123deoliveira4"; int i = Integer.parseInt(s);  AssertionError: daqui a pouco - lançada programaticamente Os dez erros e exceções principais  ExceptionInInitializerError: ao se tentar inicializar uma variável estática de um bloco de inicialização. - lançada pelo JVM class Cap5 { static int a; static {a = 2/0;} }  StackOverflowError - lançada pelo JVM  NoClassDefFoundError: quando o JVM não consegue encontrar uma classe de que precisa, por causa de um erro de linha de comando, uma questão referente ao classpath ou um arquivo .class que esteja faltando. $java ClasseX.class assertivas  pertime que se teste suas suposições durante o desenvolvimento, sem o desgaste (de tempo e sobrecarga do programa) de escrever manipuladores para exceções que se supõe que nunca ocorrerão void tam(int num) { assert (num >= 0); // código útil aqui } // ao invés de void tam(int num) { if (num >= 0) { // código útil aqui } else { ...println(“o número é negativo”); } } duas versões de assert  Muito simples: assert (y > x);  Simples: assert (num >= 0): "tá com mopa" Exception in thread "main" java.lang.AssertionError: tá com mopa at Cap5.tam(Cap5.java:11) at Cap5.fazAlgo(Cap5.java:8) at Cap5.main(Cap5.java:5)  normalmente as assertivas são ativadas quando um aplicativo está sendo testado e deuprado, porém, são desativadas quando ele é distribuido  quando a palavra “expressão” for citada em alguma questão, suponha que ela está se referindo à primeira expressão de um assert (a expressão booleana) regras das expressões de assertivas void semRetorno() {} int retornaInt() { return 0; } void vai() { int x = 1; boolean b = true; assert(x==1); assert(x = 1); assert(b); assert(x); assert true; assert 0; assert(x == 1): x; assert(x == 1): ; assert(x ==1): retornaInt(); assert(x == 1): semRetorno; assert(x == 1): new ValidAssert(); assert(x == 1): ClasseB b; } ativando assertivas  as assertivas foram adicionadas na versão 1.4 e “assert” se tornou uma palavra-chave, logo você deve utilizar “assert” como identificador ou como palavra-chave, mas não ambos  o compilador Java 5 usará a palavra-chave assert por padrão, a não ser você o instrua do contrário char assert = 'a'; $ javac Cap5.java // Error $ javac -source 1.3 Cap5.java // Warning assert(a > 0); $ javac -source 5 Cap5.java // Beleza $ javac -source 1.3 Cap5.java // Error execução de assertivas  as assertivas vêm desativadas por padrão  ativando assertivas: $ java -ea pacote.subpacote.Classe $ java -enableassertions pacote.subpacote.Classe  desativando assertivas $ java -da pacote.subpacote.Classe $ java -disableassertions pacote.subpacote.Classe  ativação e desativação seletiva: $ java -ea:com.foo.Bar $ java -ea:com.foo... $ java -ea -dsa  desativando nas classes do sistema $ java -ea -da:com.foo... uso apropriado  “apropriado” = “correto”  nunca se deve manipular uma falha de assertiva (apesar de ser possível)  o erro AssertionError não concede acesso ao objeto que o gerou (??) try { assert (num >= 0): "deu mopa"; } catch (AssertionError ae) { ae.printStackTrace(); } // uso inapropriado  não use assertivas para validar argumentos de um método public: é preciso garantir que nenhuma restrição a argumentos seja imposta public void facaAlgo(int x) { assert (x > 0); // código que mexe com x } // melhor seria lançar uma IllegalArgumentException + uso apropriado  use assertivas para validar argumentos de um método privado (pois provavelmente você controlará todos os métodos que o chamarão) private fazAlgo(byte x) { assert(x > 0); }  não use assertivas para validar argumentos de linha de comando (se precisar fazer isso, use o mecanismo de exceções)  use assertivas, mesmo em métodos públic, para procurar instruções case que sabe que nunca ocorrerão switch(x) { case 1: fazUm(); case 2: fazDois(); case 3: fazTres(); default: assert false; } ++ uso apropriado  não use assertivas que posdem causar efeitos colaterais public void fazAlgo() { assert(modificaAlgo()); // continua... } boolean modificaAlgo() { x++ = y; // outro erro aqui return true; }  uma assertiva deve deixar o programa no mesmo estado em que estava antes da expressão, pois não há garantia de que as expressões assertivas sejam sempre executadas fim