ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
Controle de Fluxo, Exceções, Assertivas
1. Grupo de Estudos - SCJP
Controle de Fluxo
Exceções
Assertivas
Eduardo Silva
ufpb, junho de 2009
2. instruções if
Formato básico:
if (expressãoBooleana) {
...println(“entrou no if”);
}
if (new Boolean(true) && !ehMentira()) {
...println(quot;no ifquot;);
}
if (a == b & b > c || c != d && d <= a) {
...println(quot;dentroquot;);
}
3. else e else-if
if (nota > 7) { if true {
...println(“maior”); ...println(“it's true”);
} else { }
...println(“não-maior”);
}
if (a < b) {
if (peso < 40) { ...println(quot;umquot;);
...println(“vôou”); }
} else if (peso < 55) { if (c > b) {
...println(“magro”); ...println(quot;doisquot;);
} else if (peso < 65) { } else {
...println(“quase”); ...println(quot;tresquot;);
} else { } else if (true) {
...println(“beleza”); ...println(quot;quatroquot;);
} }
4. 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)
if (nota > 7)
// válidos: ...println(“passou”);
if (verum == 1) ...println(“deu beleza”);
if (falsum == 0)
5. instrução switch
char ch = 'a'; char ch = 'a';
if (ch == 'c') { switch (ch) {
...println(“cê”); case 'c':
} else { ...println(“cê”);
if (ch == 'b') { break;
...println(“bê”); case 'b':
} else { ...println(“bê”);
if (ch == 'a') { break;
...println(“á”); case 'b':
} else { ...println(“á”);
...println(“outra”); break;
} default:
} ...println(“outra”);
} }
6. + 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)
7. + 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)
8. três erros de compilação:
byte b = 22;
switch (b) {
case 22:
case (b < 23):
break;
case 128:
break;
case 22:
}
9. 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”);
}
10. mais alguns
switch (new Integer(127)) {
case 127 { // faltou o “:”
...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
11. imprime o que?
short s = 12;
// --s;
switch (s) {
case 11: ...print(“11”);
default: ...print(“default”);
case 13: ...print(“13”);
}
12. 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
13. 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
14. 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
15. 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;
}
16. for aprimorado (for-each)
for (declaração : expressão)
int x;
long x2;
Long[] La = {4L, 5l, 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(x2: la);
for (int[] n: dobrado); for(int x2: dobrado);
for (int n2: dobrado[1]); for(int x3: la);
for (String s: ss); for(Dog d: animais);
for (Object o: ss);
for(Animal a: animais);
17. 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);
}
18. 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”);
19. + 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;
}
20. 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
21. 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();
}
22. 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)
try {
int a = 10 / 0;
void fazAlgo() {
}
try {
System.out.println(a);
int a = 10;
a /= 0;
try {
} catch (ArithmeticException e) {
int b = 10 / 0;
System.out.println(quot;no catchquot;);
} finally {
return;
...println(“finally”);
} finally {
} catch (Exception e) {
System.out.println(quot;no finallyquot;);
...println(“catch”);
}
}
} // o que será impresso?
System.out.println(b);
23. propagação de exceções
class Pilha {
public static void main(String[] args) {
new Cap5().facaUm();
}
void facaUm() { fazDois()
facaDois();
fazUm()
}
void facaDois() {
main()
int a = 1/0;
}
}
Exception in thread quot;mainquot; java.lang.ArithmeticException: / by zero
at Cap5.facaDois(Cap5.java:11)
at Cap5.facaUm(Cap5.java:8)
at Cap5.main(Cap5.java:5)
24. 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
25. 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(quot;myfile.txtquot;, quot;rquot;);
byte[] b = new byte[1000];
raf.readFully(b, 0, 1000);
} catch (FileNotFoundException e) {
System.out.println(quot;file not foundquot;);
} catch (IOException e) {
System.out.println(quot;IO Errorquot;);
}
26. 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
27. + 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();
}
}
28. 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;
}
29. 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()
}
30. 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
31. 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
32. 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 = quot;123deoliveira4quot;;
int i = Integer.parseInt(s);
AssertionError: daqui a pouco
- lançada programaticamente
33. 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
34. 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”);
}
}
35. duas versões de assert
Muito simples: assert (y > x);
Simples: assert (num >= 0): quot;tá com mopaquot;
Exception in thread quot;mainquot; 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)
36. 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;
}
37. 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
38. 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...
39. 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): quot;deu mopaquot;;
} 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
40. + 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;
}
41. ++ 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