Seja bem-vindo a série de postagens sobre a certificação Java. Como funciona, o que fazer para comprar, marcar o dia da prova e o principal, o que estudar.
Para ver o índice da série e as datas das publicações, acesse este link
Parte 3 – Operadores, decisões e loops
Neste post, vamos dar mais um passo nos detalhes da linguagem quanto aos operadores, decisões e loops.
Objetivos do exame
- Precedência com uso de parenteses
- If, if/else e operadores ternários
- Usando o switch
- Usando while
- Loops for
- Do/while loops
- Break e continue
Operadores Java
Para o exame, será preciso conhecer os operadores Java e como ela é resolvida. Nem sempre a operação será resolvida da esquerda para a direita. Ex:
int y = 8;int x = 2 - 5 + 3 * 4 - --y;
No exemplo acima, é feita a subtração de uma unidade de y, após é feita a multiplicação e depois resolve da esquerda para a direita. O resultado a operação acima é 2.
Os operadores que aparecerão na prova são: (+), (-), (*), (/) e resto da divisão (%). Os operadores (*, / e %) tem precedência sobre os operadores (+ e -). Para dar preferência a um operador de menos precedência, utilizamos os parenteses.
int x = (2 - 5 + 3) * 4 - --y;
Agora o resultado é -7
Agora o resultado é -7
O operador + e += pode ser aplicado também a String, resultando na concatenação. O operador resto (%) é exatamente o resto da divisão entre dois números.
System.out.println(21 / 4); //resultado = 5
System.out.println(21 % 4); //resultado = 1
Você deve lembrar que se fizer uma operação com dois tipos de números diferentes, o tipo com menos tamanho será convertido para o maior tipo. Ex:
int y = 8;
long x = 10;
int w = y + x; //erro de compilação
long x = 10;
int w = y + x; //erro de compilação
Se um dos valores for de ponto flutuante, o valor inteiro será promovido automaticamente para ponto flutuante. No caso dos dois valores forem de ponto flutuante, o que vale é o double.
double a = 2.2; float b = 3.3f; float c = a * b;//erro de compilação
Cuidado com algumas pegadinhas na prova.
Inversão de valores
int x = -14;System.out.println(x); //print -14
x = -x;
System.out.println(x); //print 14
Qualquer valor abaixo de int que tiver uma operação matemática executada, será transformado em int.
short a = 1;
short b = 2;
short c = a + b; //erro de compilação
short b = 2;
short c = a + b; //erro de compilação
Porem se utilizarmos operadores de incremento e decremento (-- e ++) para atribuir a variável, é feito o cast automaticamente.(++) e (--) tem preferência aos operadores binários. Dependendo da localização do operador, o resultado da expressão pode ser diferente. Ele pode ser colocado antes ou depois da variável.
short a = 1;
short b = ++a; //ok
int x = ++b + a--; //válido
System.out.println(x); //Resultado é 5
Cast de dados primitivos
Quanto um valor literal não cabe no tipo de variável declarada, ainda é possível atribuir o valor fazendo um cast. Com o cast e possível associar um valor de ponto flutuante em um int por exemplo. Um valor maior a um short. Porém cuidado com este tipo de conversão, pois poderá haver perda de consistência. Cuidado com atribuição dentro de atribuições.
x = 1y = (x = 3) //ok, y = 3
Operadores relacionais
Sempre retornam um valor booleano. O operador instanceof não é cobrado no exame menor que (<), menor ou igual(<=), maior que (>) e maior ou igual (>=).
Operadores lógicos
Temos três operadores lógicos: e ( & ), or inclusivo ( | ) e or exclusivo( ^ )Operadores de curto circuito
Para este tipo de operador, a diferença é que se a expressão da direita retornar true, o restante da expressão não é avaliada. Um exemplo clássico deste uso é a verificação de uma variável.
if (a != null && a.equals("a")){ }
Caso a variável a for null, então a segunda expressão nunca será executada, evitando uma exceção. Para o exame, é possível ter uma pergunta que incrementa uma variável em uma expressão. Ex:
String a = "a"; int b = 6; if (a != null && b++ == 7){ System.out.println(a); } System.out.println(b);
O que acontece se executarmos o código acima? A variável a não será impressa, porém o valor da variável b será 7 após o if. Caso a variável a fosse null, então o valor de b seria 6. A variável b não é 7 no momento do if, pois está utilizando um operador de incremento posterior.
Comparação de igualdade (==)
É possível comparar objetos, números primitivos e valores booleanos.
System.out.println(500 == 5_0_0.0_0_0__0); //true
O exemplo acima compila e retorna true, pois o Java consegue converter o valor da esquerda para double. Para comparação de objetos, o operador de igualdade é aplicado às referências aos objetos, não os objetos para os quais eles apontam. Duas referências são iguais se e somente se apontarem para o mesmo objeto, ou ambos apontam para null.
Relação completa dos operadores Java:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/opsummary.html
Java Statements
O controle de fluxo de um código Java é feito pelos statements, conhecidos como: if/else, if/then/else, operador ternário, switch, while, do-while e for.
If sempre deve retornar um booleano, porém podemos ter atribuições de variáveis ou incremento de valores dentro da expressão. Então muito cuidado ao analisar questões como esta:
int x = 1; if (++x > 1) System.out.println("x is greater than one!");
No código acima, teremos a impressão da mensagem pois a variável x foi incrementada antes da verificação da condição. E também como tínhamos apenas uma instrução dentro do if, não precisamos das chaves. Na prova pode ocorrer que o código não esteja identado e te induza ao erro.
int x = 1; if (x++ > 1) System.out.println("x is greater than one!"); System.out.println("x is " + x);
No código acima, você poderá ser questionado sobre a saída da execução. Olhe com cuidado, pois o if não possui abertura de chaves, então somente a primeira linha após o if seria executada caso a expressão retornasse true. O que não é o caso. Como o x é incrementado depois, ele não será maior que 2. Porém o segundo print não esta dentro do if e a saída da execução será 2.
Para o if/else, a regra é a mesma. Caso tenha apenas uma instrução apos o if, não é necessário as chaves.
int x = 1; if (x++ > 1) System.out.println("x is greater than one!"); else System.out.println("x is not greater than one"); System.out.println("x is " + x);
Neste outro código, o último System.out sempre será executado independente do resultado da expressão. Uma vez executado o código abaixo da expressão verdadeira, os demais ifs serão ignorados. Então a ordem dos ifs é importante.
int hourOfDay = 10; if(hourOfDay < 15) { System.out.println("Good Afternoon"); } else if(hourOfDay < 11) { System.out.println("Good Morning"); // nunca será executado } else { System.out.println("Good Evening"); }
Sempre verifique se a expressão esta verificando uma condição booleana. O código abaixo não compila, pois esta sendo feita uma atribuição dentro do if.
int age = 18; if(age = 18) System.out.println("Major!"); //não compila
Operador ternário
Um dos operadores que mais pode causar confusão no momento da prova. O operador é relativamente simples, porém se ele aparecer de forma encadeada, ai fica difícil e demorado para verificar o resultado. Pense no operador ternário como um if/then/else.
if ? then : elseint x = 1; int y = x > 1 ? 10 : 20;O código acima seria o mesmo que:
int x = 1; int y; if (x > 1) { y = 10; } else { y = 20; }Agora um exemplo que talvez você encontre na prova:
int x = 1; int y = x >= 1 ? x == 1 ? 2 : 3 : 20;
Se o x for maior ou igual a 1, então ele avalia outra expressão. Se o x for igual a 1, então retorna 2, senão retorna 3;
Switch
A partir do Java 7, a String também foi incorporada no switch. Os tipos de dados suportados são:■ int e Integer
■ byte e Byte
■ short e Short
■ char e Character
■ int e Integer
■ String
■ enum
Somente os tipos acima são permitidos. Não tente utilizar um double ou long por exemplo. Você terá um erro de compilação. No caso do switch, sempre devemos utilizar o break para que o fluxo siga para fora do switch, pois caso não utilizar, o Java continua verificando as condições.
int age = 1; switch(age) { default: System.out.println("default"); case 2: System.out.println("two years old"); case 3: System.out.println("three years old"); }
O que acontece ao executar o bloco de código acima? Por mais que nenhuma condição seja atendida explicitamente, foi utilizado o default que será executado quando nenhuma condição for verdadeira. E como não foi utilizada a instrução break, todas as condições abaixo serão executadas.
Todo valor da expressão case deve ser uma constante e do mesmo tipo da expressão switch. Pode ser um literal, um enum, uma variável final.
String var = "test1"; final String var1 = "test2"; switch (args[0]) { case "test": System.out.println("test"); case var: //erro de compilação System.out.println("test1"); case var1: System.out.println("test2"); }
While
Um while é parecido com o if, porém a instrução dentro do while é executada enquanto a condição for verdadeira.
int x = 0; while (x++ < 10) System.out.println(x);
Assim como o if, não é obrigatório ter a abertura de chaves. Neste caso o print será executado 10 vezes e então continuar o fluxo. Caso o x não fosse incrementado dentro do while, então teríamos um loop infinito. Seria a mesma coisa que fazer um while (true).
Do while
A diferença para o while é que o do/while será executado pelo menos uma vez antes de verificar a expressão booleana.
Comando for
O comando for é um pouco mais complexo que o while e o do/while. Ele tem duas formas. A primeira chamada de forma básica existente desde o Java 1. A partir do Java 5, temos o for-each. O for básico possui três blocos (inicialização; expressão booleana; incremento) e todos eles são opcionais. Temos apenas como obrigação separar com ponto e virgula.
for (; ; ) System.out.println("infinite loop!");
A instrução acima é válida e faz um loop infinito devido ao não controle do fluxo. Podemos utilizar múltiplas instruções nos blocos do for. Inicializando varias variáveis, verificando expressões booleanas e incrementando algumas variáveis.
for (int x = 0, y = 0; x <= 10 && y <= 10 ; x++, y++){ System.out.println(x); System.out.println(y); }
No exemplo acima, estamos inicializando duas variáveis, comparando os valores e incrementado. Esse tipo de questão é bem comum na prova, então pratique bastante. Não é possível redeclarar uma variável dentro do for. Ex:
public static void main(String[] args) { int y = 1; for (int x = 0, y = 0; x <= 10 && y <= 10 ; x++, y++){ //erro }
Para o código acima compilar, basta retirar a declaração as variáveis de dentro do for e passar para fora do for. Outro detalhe é que não é possível declarar tipos diferentes no bloco de inicialização. E lembre-se, caso a variável tenha sido declarada no bloco de inicialização do for, ela é de escopo local do for e não pode ser utilizada fora dele.
For-each
O for-each foi introduzido na versão 5 do Java e para o exame é preciso reconhecer uma iteração utilizando o List e ArrayList:
List<String> names = Arrays.asList("Sara", "Lisa", "Andrew"); for (String name : names) { System.out.println(name); }
O for é divido em dois blocos. O primeiro é a declaração do objeto que esta dentro da coleção. No caso, para uma lista de Strings é declarado apenas o objeto String. Separamos o bloco de inicialização do bloco da lista a ser iterada por dois pontos.
Controle de fluxo avançado
Loops podem conter outros loops, então as coisas podem ficar um pouco mais complicadas no exame. O que é bem comum.
int[][] matrix = {{4, 3, 2, 1}, {3, 4, 5, 6, 3}, {2, 3, 4, 5, 6, 7}}; for (int[] ints : matrix) { for (int i = 0; i < ints.length; i++) { System.out.print(ints[i] + "\t"); } System.out.println(); }
Dentro destes loops ainda é possível que tenha uma lógica e você deve acertar o resultado de saída.
int x = 0, y = 2; while (x < 5) { x++; do { y++; } while (y < 10); } System.out.println(x); System.out.println(y);Qual o resultado de x e y apos a execução do código acima?
break e continue
A diferença entre o break e o continue é que o break irá terminal o fluxo do loop atual e continuará para fora do loop e o continue interromperá o loop atual e retornará para a validação booleana se deve continuar com o loop. Existem ainda os labels, porém não são cobrados na prova.
Para saber mais:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
Conclusão
O tópico de controle de fluxo e repetição sem dúvida é um dos mais importantes do exame, pois a maioria dos exemplos de código terão algum if ou loop. Ocasionalmente a pergunta pode ser de um determinado assunto, porém a resposta pode ser um erro de compilação devido ao if, for ou loop que não compila.
Bons estudos e até a próxima!
Comentários
Postar um comentário