- Aprender
- Computação e TI
- Programação
- Programação orientada a objetos com Java
- Condições e laços em Java
Condições e laços em Java
if, cadeias de else if e expressões switch, e repita instruções com laços while, do-while e for, usando break e continue quando forem úteis. Depois, aplique os padrões comuns de laços para contar, somar, calcular médias, encontrar o maior valor, fazer buscas e imprimir tabelas, e verifique seus laços acompanhando cada passagem.BásicoAula 2 de 11 do curso Curso de Programação orientada a objetos com Java
O que você vai aprender
- Construa condições verdadeiras ou falsas a partir de comparações e combine-as com operadores lógicos para que um programa teste exatamente a situação desejada.
- Compare valores e armazene os resultados como booleanosUse os seis operadores relacionais com números e caracteres, guarde os resultados em variáveis
booleane compare cadeias de caracteres e números decimais corretamente. - Combine condições com &&, || e !Una e negue condições com os operadores lógicos, preveja seus resultados com tabelas-verdade e use a avaliação de curto-circuito e as leis de De Morgan para escrever testes corretos e legíveis.
- Compare valores e armazene os resultados como booleanos
- Faça um programa executar instruções diferentes conforme as condições, desde um único
ifaté cadeias deelse if, o operador condicional eswitch.- Execute código condicionalmente com if e elseEscreva instruções
ifeif-elsecom blocos corretos, evite os erros clássicos de chaves, ponto e vírgula e escopo, e aninhe decisões ou escolha um valor com o operador condicional. - Escolha um entre vários casos com cadeias de else-ifUse cadeias de
else ifpara escolher exatamente um entre vários resultados, ordene as condições corretamente e teste os valores-limite para que nenhum valor caia em uma lacuna ou em dois casos. - Selecione por valor com switchUse instruções
switche expressõesswitchpara escolher pelo valor de uma variável, com casos de seta, vários rótulos por caso,defaulteyield, e reconheça a continuação entre casos na forma mais antiga com dois-pontos.
- Execute código condicionalmente com if e else
- Escreva laços
while,do-whileeforque sejam executados o número certo de vezes e parem quando devem, e controle-os combreakecontinue.- Repita enquanto uma condição for verdadeira com whileEscreva laços
whileque comecem, sejam atualizados e parem corretamente, usewhile (true)combreakpara repetições sem duração definida e acompanhe um laço a cada passagem. - Execute o corpo pelo menos uma vez com do-whileUse o laço
do-whilequando o corpo precisar ser executado antes do primeiro teste, como em verificações de entrada e menus, e evite suas armadilhas de escopo e ponto e vírgula. - Percorra intervalos de contagem com laços forEscreva laços
forque contem em ordem crescente, decrescente e em passos, preveja quantas vezes eles serão executados, evite erros de uma unidade e escolha o tipo certo de laço para cada tarefa. - Encerre laços ou pule iterações com break e continueEncerre um laço antecipadamente com
break, pule o restante de uma passagem comcontinue, saia de laços aninhados com umbreakcom rótulo e mantenha fáceis de acompanhar os laços com saídas antecipadas.
- Repita enquanto uma condição for verdadeira com while
- Reconheça e combine os padrões comuns de laços: contar e somar, encontrar valores extremos, fazer buscas, processar algarismos e aninhar laços, e verifique os laços por meio de rastreamento e testes.
- Conte valores, some-os e calcule sua médiaUse contadores e acumuladores com entrada controlada por sentinela, calcule médias e porcentagens sem erros de divisão inteira e proteja-se contra entrada vazia e estouro.
- Encontre valores extremos, faça buscas e processe algarismosAcompanhe o maior ou o menor valor encontrado até o momento, faça buscas com uma variável sinalizadora ou uma saída antecipada, teste se algum ou todos os valores atendem a uma condição e decomponha números algarismo por algarismo.
- Aninhe laços, acompanhe sua execução e teste-osEscreva laços aninhados para tabelas e padrões, preveja quantas vezes o corpo interno será executado, acompanhe laços com uma tabela e teste-os com casos extremos para encontrar erros de uma unidade e laços infinitos.
- Conte valores, some-os e calcule sua média
Guia de estudo de Condições e laços em Java
1Construa condições verdadeiras ou falsas
Uma condição transforma uma pergunta sobre os dados do programa em um valor verdadeiro ou falso. Comparações permitem perguntar se um número atinge um limite ou se um texto corresponde a um comando; operadores lógicos permitem unir esses testes. Leia as partes de uma condição na ordem em que Java as avalia e depois verifique o resultado combinado. Assim, é possível expressar um intervalo, uma exceção ou uma verificação de proteção para uma divisão sem deixar que um pequeno erro de operador altere a regra.
1.1 Comparações e valores booleanos
Uma condição tem o tipo boolean: ela produz true ou false. Java precisa desse resultado explícito em uma condição de if ou de laço. Um inteiro sozinho não é uma condição, portanto while (count) não compila; count > 0 faz uma pergunta clara de resposta verdadeira ou falsa.
Compare números e caracteres
| Operador | Pergunta |
|---|---|
< | O valor à esquerda é menor? |
<= | Ele é menor ou igual? |
> | Ele é maior? |
>= | Ele é maior ou igual? |
== | Os valores são iguais? |
!= | Os valores são diferentes? |
Com int a = 7; e int b = 10;, a < b e a != b são true, enquanto a >= b é false. Tipos numéricos diferentes podem ser comparados: 3 == 3.0 é true depois que Java faz uma conversão de ampliação do inteiro para double.
Uma comparação de char usa códigos numéricos Unicode. Por exemplo, 'a' < 'b' é true. O mesmo ocorre com 'Z' < 'a': seus códigos são 90 e 97. Nessa ordenação, todas as letras maiúsculas ASCII de A a Z precedem as minúsculas de a a z.
Armazene uma resposta útil
int age = 17;
boolean isAdult = age >= 18;
System.out.println(isAdult);
A comparação produz false, que é armazenado em isAdult e depois impresso. Um nome significativo permite que o código posterior diga diretamente if (isAdult).
Mantenha atribuição e comparação distintas. = armazena um valor; == compara valores. Para um inteiro, if (x = 5) falha porque a atribuição produz um inteiro. Para um booleano, if (done = true) compila, define done como true e executa o ramo. Para testar a variável sinalizadora existente, escreva if (done).
Compare texto e decimais calculados
Use command.equals("quit") para comparar os caracteres de uma cadeia de caracteres. O texto digitado como “quit” corresponde; “Quit” não corresponde. Use equalsIgnoreCase quando a diferença entre maiúsculas e minúsculas não importar e !command.equals("quit") para testar se o texto é diferente. O operador == verifica se as cadeias de caracteres se referem ao mesmo objeto, portanto não é adequado para comparar o conteúdo de uma entrada do usuário.
O formato binário de ponto flutuante não consegue armazenar muitas frações decimais exatamente. 0.1 + 0.2 produz 0.30000000000000004, portanto 0.1 + 0.2 == 0.3 é false. Uma comparação com tolerância verifica a distância entre os valores calculados:
double sum = 0.1 + 0.2;
boolean closeEnough = Math.abs(sum - 0.3) < 1e-9;
Aqui Math.abs torna a diferença não negativa; a pequena diferença está abaixo de 1e-9, portanto closeEnough é true. Escolha uma tolerância adequada à precisão exigida pelo cálculo. Comparações exatas de valores int não têm o problema de arredondamento em ponto flutuante.
Teste divisibilidade e intervalos
n % 3 == 0 testa se um inteiro é divisível por 3. Para números ímpares, use n % 2 != 0: o teste inclui valores ímpares negativos, pois -7 % 2 é -1.
Escreva cada lado de um teste de intervalo separadamente: 0 < x && x < 10. Java não consegue ler 0 < x < 10 como uma cadeia matemática: a primeira comparação já produz um booleano, que não pode ser comparado com 10.
Principais conclusões
- Uma condição deve produzir um
boolean. - Use
=para atribuir e==para comparar valores numéricos. - Compare o conteúdo de cadeias de caracteres com
equalsouequalsIgnoreCase. - Compare decimais calculados com uma tolerância adequada.
- Use
n % 2 != 0para inteiros ímpares, incluindo os negativos.
1.2 Condições combinadas e avaliação de curto-circuito
Operadores lógicos combinam condições completas, verdadeiras ou falsas. Leia uma condição combinada como uma regra sobre os dados e depois teste valores que devem ser aceitos e valores que devem ser rejeitados.
Una e negue testes
&& significa e: ambas as partes devem ser verdadeiras. || significa ou: pelo menos uma parte deve ser verdadeira, inclusive quando ambas são. ! significa não e inverte um valor booleano.
| p | q | p && q | p || q |
| --- | --- | --- | --- |
| true | true | true | true |
| true | false | false | true |
| false | true | false | true |
| false | false | false | false |
Uma temperatura confortável de 18 a 24 °C precisa dos dois limites: temp >= 18 && temp <= 24. Estar fora desse intervalo significa temp < 18 || temp > 24. Unir os limites internos com || aceita qualquer número: abaixo de 18, o teste do limite superior é verdadeiro e, acima de 24, o teste do limite inferior é verdadeiro.
Cada operando deve ser uma expressão booleana. Escreva x == 1 || x == 2, pois x == 1 || 2 coloca um inteiro onde um booleano é necessário. Para um inteiro, !x > 5 é inválido; !(x > 5) nega a comparação inteira.
Avalie apenas o necessário
Java avalia && e || da esquerda para a direita e usa a avaliação de curto-circuito quando a parte esquerda determina a resposta. Com &&, um lado esquerdo falso faz o lado direito ser ignorado. Com ||, um lado esquerdo verdadeiro faz o lado direito ser ignorado.
int total = 36;
int count = 0;
boolean largeAverage = count != 0 && total / count > 10;
A primeira comparação é falsa, portanto a divisão é ignorada e largeAverage passa a ser false. Inverta os operandos e a divisão ocorrerá antes da verificação de proteção; a divisão inteira por zero lança uma ArithmeticException. Coloque a verificação de segurança antes do cálculo que ela protege.
Torne o agrupamento visível
Da maior para a menor precedência, os operadores relevantes são !, comparações relacionais (<, <=, >, >=), comparações de igualdade (==, !=), && e depois ||. Assim, a || b && c é agrupado como a || (b && c). Quando a é verdadeiro e b e c são falsos, essa expressão é verdadeira; (a || b) && c é falsa. Os parênteses mostram qual regra você pretende usar.
As leis de De Morgan deslocam uma negação por uma condição combinada:
!(p && q)equivale a!p || !q.!(p || q)equivale a!p && !q.
Negue cada parte e troque o operador que as une. Aplicar isso ao intervalo de temperatura mostra que !(temp >= 18 && temp <= 24) equivale a temp < 18 || temp > 24.
Expresse uma regra com uma exceção
Um ano bissexto no calendário gregoriano é divisível por 4, exceto que um ano de início de século deve ser divisível por 400:
boolean leap = (year % 4 == 0 && year % 100 != 0)
|| year % 400 == 0;
A primeira parte aceita 2024. Ela rejeita 1900 porque 1900 é um ano de início de século; o teste final aceita 2000 porque ele é divisível por 400. O ano 2026 não atende a nenhuma das partes.
Booleanos com nomes ajudam a tornar testes mais longos claros, como isWeekend || isHoliday. Para dois booleanos, ^ é o OU exclusivo: exatamente um operando deve ser verdadeiro, como em !=. Os operadores simples & e | também calculam o e/ou booleano, mas avaliam ambos os operandos; use && e || para condições com curto-circuito.
Principais conclusões
&&exige ambas as condições;||exige pelo menos uma.- Uma verificação de proteção com curto-circuito deve vir antes da expressão que protege.
&&tem precedência maior que||; os parênteses podem alterar o resultado.- As leis de De Morgan negam ambas as partes e trocam
&&por||e vice-versa. - Cada lado de um operador lógico deve ser uma expressão booleana completa.
- Os operadores simples
&e|avaliam ambos os operandos.
2Escolha o caminho que um programa segue
Uma decisão direciona a execução por um caminho selecionado. Um único teste pode habilitar uma ação, um par de ramos pode escolher entre duas ações e uma cadeia pode atribuir um resultado a partir de vários intervalos. Quando a escolha depende de valores exatos de uma variável, switch oferece outra forma clara. Acompanhar o caminho significa verificar quais condições são alcançadas, qual ramo é executado e quais variáveis permanecem disponíveis depois.
2.1 Ramos, blocos e escolha de valores
Um if executa um bloco quando sua condição é verdadeira. Um if com else escolhe exatamente um de dois blocos. Depois que o bloco escolhido termina, a execução continua com a instrução seguinte.
Escolha um caminho
int age = 16;
if (age >= 18) {
System.out.println("Adult ticket");
} else {
System.out.println("Youth ticket");
}
System.out.println("Next customer");
A condição é falsa, portanto a saída é “Youth ticket”, seguida de “Next customer”. A última instrução não pertence a nenhum dos ramos. Coloque a condição booleana entre parênteses e as instruções de cada ramo entre chaves.
Sem chaves, apenas a próxima instrução pertence a um if. A indentação não agrupa código. Neste exemplo com erro, a segunda mensagem aparece para qualquer pontuação:
if (score < 50)
System.out.println("Not passed");
System.out.println("Try again");
Chaves ao redor das duas instruções de impressão tornam ambas condicionais. Outro erro é um ponto e vírgula imediatamente após a condição: if (x > 10); tem um corpo vazio. Um bloco que venha em seguida é executado independentemente, e um else depois desse bloco independente não tem um if correspondente.
Mantenha um resultado disponível
Uma variável declarada dentro de um bloco só é visível dentro dele. Declare um resultado antes dos ramos quando o código posterior precisar dele:
String ticket;
if (age >= 18) {
ticket = "Adult ticket";
} else {
ticket = "Youth ticket";
}
System.out.println(ticket);
Ambos os caminhos possíveis atribuem um valor a ticket, portanto imprimi-la depois é válido. Se apenas o ramo verdadeiro atribuísse um valor a ela, Java rejeitaria a leitura posterior: a variável poderia não ter sido inicializada. Declarar ticket separadamente dentro de cada ramo também deixaria ticket indisponível depois da decisão.
Coloque uma decisão dentro de outra
Um if aninhado só executa seu teste quando a execução chega ao ramo que o contém:
if (hasTicket) {
if (age < 12) {
System.out.println("Child seat");
} else {
System.out.println("Standard seat");
}
} else {
System.out.println("Buy a ticket first");
}
Uma pessoa sem ingresso chega ao else externo; a verificação de idade é ignorada. Se ambos os testes aninhados apenas condicionam a mesma ação e nenhum deles tem else, eles podem se tornar if (hasTicket && age < 12).
A regra do else pendente associa um else ao if mais próximo ainda sem correspondência. Sem chaves, alinhá-lo visualmente com um if externo não altera essa regra. Para um teste externo de x positivo seguido de um teste interno de y positivo, o próximo else pertence ao teste de y. São necessárias chaves ao redor da decisão interna completa quando o else deve pertencer ao teste externo.
Escolha um valor com ?:
O operador condicional escolhe um de dois valores:
int n = 7;
String label = n % 2 == 0 ? "even" : "odd";
A condição é falsa, portanto a expressão produz “odd”. Sua forma é condition ? valueIfTrue : valueIfFalse. Use-o para uma escolha curta de valor; use um if quando os ramos executarem várias ações. Expressões condicionais aninhadas logo tornam difícil acompanhar o caminho escolhido.
Principais conclusões
- As chaves agrupam todas as instruções que pertencem a um ramo.
- Um
elsese associa aoifmais próximo ainda sem correspondência. - Um resultado necessário após uma decisão deve estar no escopo e receber um valor em todos os caminhos que chegam ao seu uso.
?:escolhe um valor entre duas expressões.
2.2 Casos ordenados e valores-limite
Uma cadeia de else if testa condições em ordem e seleciona a primeira verdadeira. Depois que esse ramo é executado, as condições restantes são ignoradas. Um else final trata os valores restantes; sem ele, a cadeia pode não executar nenhuma ação.
Ordene limiares sobrepostos
Para pontuações de 0 a 100, teste primeiro a nota mais alta:
String grade;
if (score >= 90) {
grade = "A";
} else if (score >= 80) {
grade = "B";
} else if (score >= 70) {
grade = "C";
} else if (score >= 60) {
grade = "D";
} else {
grade = "F";
}
Para 85, o primeiro teste falha e o segundo é satisfeito. O programa atribui “B” sem verificar os limiares restantes. Chegar a score >= 80 já significa que a pontuação é menor que 90, portanto um limite superior adicional é desnecessário.
Se score >= 60 aparecesse primeiro, toda pontuação de aprovação receberia “D”. Trabalhe do caso correspondente mais restritivo para os mais abrangentes. Essa regra de ordenação importa porque várias condições podem ser verdadeiras, embora apenas um ramo seja executado.
Trate primeiro o caso combinado
FizzBuzz tem um caso especial em que duas regras se sobrepõem: múltiplos de 3 e de 5 precisam de “FizzBuzz”. Teste esse caso antes de qualquer um dos testes individuais de divisibilidade:
if (n % 15 == 0) {
System.out.println("FizzBuzz");
} else if (n % 3 == 0) {
System.out.println("Fizz");
} else if (n % 5 == 0) {
System.out.println("Buzz");
} else {
System.out.println(n);
}
O teste % 15 == 0 aceita 30; 9 chega a “Fizz”, 10 chega a “Buzz” e 7 chega ao ramo final. Começar com % 3 == 0 aceitaria 30 cedo demais e imprimiria apenas “Fizz”.
Escolha um resultado ou várias ações
Instruções if separadas são decisões independentes. Com x = 15, um if (x > 10) pode imprimir “big” e um if (x > 0) seguinte também pode imprimir “positive”. Uni-los com else if torna o segundo teste inalcançável sempre que o primeiro for verdadeiro. Use testes independentes quando ambas as ações puderem ser necessárias; use uma cadeia para selecionar um resultado.
Verifique limites e valores inválidos
Uma cadeia para temperaturas inteiras com temp < 10, depois temp > 10 && temp < 25 e depois temp >= 25 deixa de fora exatamente 10. Substitua o segundo teste por temp < 25: chegar a ele já significa que o primeiro teste falhou, portanto o valor é pelo menos 10. Um else final trata então 25 e valores maiores.
Para cada limiar, experimente o valor imediatamente abaixo dele, o próprio limiar e o valor imediatamente acima dele. Para a cadeia de notas, 89, 90 e 91 revelam se o limite de A está incluído corretamente. Teste também os limites gerais.
Valide uma pontuação antes de atribuir uma nota: coloque score < 0 || score > 100 primeiro e informe “Invalid score” nesse caso. Os ramos posteriores operam então apenas sobre pontuações válidas; 150 não pode receber “A” acidentalmente. A validação é um primeiro caso separado, não uma correção depois que a nota já foi escolhida.
Principais conclusões
- A primeira condição verdadeira em uma cadeia seleciona o único ramo executado.
- Coloque casos sobrepostos mais restritos antes dos mais abrangentes.
- Use instruções
ifseparadas quando várias ações puderem se aplicar. - Teste os valores em cada limiar e próximos a ele.
- Rejeite entradas inválidas antes de classificar as válidas.
2.3 Casos de switch e resultados de expressões
Um switch seleciona um caso comparando um valor com rótulos fixos. Ele é adequado para comandos nomeados e escolhas numeradas. Use uma cadeia de else if quando a escolha depender de um intervalo ou de várias variáveis.
Encontre valores exatos
Um switch por valor aceita seletores char, byte, short, int, seus tipos empacotadores, String e tipos enum. Sem recursos em prévia, seletores long, float, double e boolean não são aceitos. Os rótulos devem ser constantes: uma condição como score >= 90 não é um rótulo de valor.
switch (day) {
case 1, 2, 3, 4, 5 -> System.out.println("Weekday");
case 6, 7 -> System.out.println("Weekend");
default -> System.out.println("Invalid day");
}
Um caso com seta executa apenas seu próprio código, sem continuação para o caso seguinte. Vírgulas agrupam vários rótulos para uma ação. Um dia igual a 6 imprime “Weekend”; um dia igual a 9 não corresponde a nenhum valor listado e imprime “Invalid day”.
Rótulos de String correspondem a conteúdos exatos, com distinção entre maiúsculas e minúsculas. Um comando “Start” não corresponde a case "start". Um rótulo duplicado é um erro de compilação, e um mesmo switch não pode misturar casos com seta e casos com dois-pontos.
Produza um valor
Uma expressão switch calcula um resultado:
int days = switch (month) {
case 1, 3, 5, 7, 8, 10, 12 -> 31;
case 4, 6, 9, 11 -> 30;
case 2 -> 28;
default -> 0;
};
Em um ano não bissexto, o mês 9 produz 30, o mês 2 produz 28 e o mês inválido 13 produz 0. O ponto e vírgula após a chave de fechamento encerra a declaração da variável.
Uma expressão deve ser exaustiva: cada valor possível do seletor deve ter um resultado. Para estes exemplos com int e String, inclua default. Uma instrução switch por valor pode omitir default; nesse caso, um valor sem correspondência não executa nenhum caso. Uma expressão que produz um valor não pode simplesmente deixar de produzir seu resultado.
Forneça um resultado a um bloco com yield
Um caso que faz cálculos antes de escolher seu valor precisa de um bloco:
int days = switch (month) {
case 2 -> {
boolean leap = (year % 4 == 0 && year % 100 != 0)
|| year % 400 == 0;
yield leap ? 29 : 28;
}
case 4, 6, 9, 11 -> 30;
case 1, 3, 5, 7, 8, 10, 12 -> 31;
default -> 0;
};
yield fornece o valor do caso à expressão switch. Fevereiro produz 29 em 2024 e 28 em 2026. Uma única expressão após uma seta, como case 2 -> 28;, não precisa de yield.
Leia a forma mais antiga com dois-pontos
switch (level) {
case 1:
System.out.println("Bronze");
case 2:
System.out.println("Silver");
break;
case 3:
System.out.println("Gold");
break;
}
Para o nível 1, a execução entra no primeiro caso e continua no segundo, imprimindo tanto “Bronze” quanto “Silver”. Isso é a continuação entre casos: um rótulo com dois-pontos não interrompe a execução. break encerra o switch. Rótulos com dois-pontos em sequência podem compartilhar uma ação deliberadamente; a falta de um break após uma ação pode executar a próxima acidentalmente.
Um switch de char pode agrupar 'a', 'e', 'i', 'o', 'u' em um resultado “vowel”, com default produzindo “other”. O mesmo princípio de valor exato se aplica a caracteres, comandos e escolhas numéricas.
Principais conclusões
- Use
switchpara rótulos fixos de um seletor. - Casos com seta não continuam para o caso seguinte.
- Uma expressão switch deve produzir um resultado para cada valor possível do seletor.
- Um caso com bloco fornece o resultado da expressão com
yield. - Um caso com dois-pontos pode continuar para o seguinte sem
break. - Casos de String correspondem a conteúdos exatos, com distinção entre maiúsculas e minúsculas.
3Controle a repetição e a parada
A repetição depende tanto de uma condição quanto de uma alteração no estado do programa. Acompanhe um laço desde seus valores iniciais, passando pelo teste, pelo corpo e pela atualização, para ver quando ele para. As três formas de laço colocam essas partes em posições diferentes: antes do corpo, depois dele ou juntas em um cabeçalho. Saídas antecipadas e passagens puladas acrescentam opções úteis, mas também tornam importante acompanhar a ordem de execução com cuidado.
3.1 Testes do laço while e alterações de estado
Um laço while testa sua condição antes de cada passagem. Se a condição for verdadeira, Java executa o corpo e retorna ao teste. Se for falsa, a execução continua depois do laço. Um primeiro teste falso significa zero passagens.
Acompanhe início, teste, corpo e atualização
int i = 1;
while (i <= 5) {
System.out.println(i);
i++;
}
O valor inicial é 1. Cada passagem imprime o valor atual e depois o incrementa. A quinta passagem imprime 5 e altera i para 6. O teste seguinte é falso, portanto o laço termina. Há cinco execuções do corpo, mas seis testes da condição: um antes de cada passagem e um teste falso final.
Um laço de contagem precisa de um valor inicial, um teste e uma atualização que o aproxime da parada. Omita i++ e esse laço imprimirá 1 para sempre. Um ponto e vírgula indevido é outra armadilha: em while (i <= 5);, a instrução vazia é o corpo. Quando i começa dentro do intervalo, o bloco posterior nunca é alcançado e não pode atualizá-lo.
Pare quando um limite for ultrapassado
A igualdade costuma ser um teste de parada frágil. Começar em 0 e somar 3 passa por 0, 3, 6, 9, 12 e assim por diante. O teste i != 10 não consegue perceber que 10 foi ultrapassado, pois 10 é pulado. O teste i < 10 termina depois de processar 9. Escolha um limite que corresponda à direção da atualização.
Alguns laços se repetem um número desconhecido de vezes. Por exemplo:
int amount = 1;
int days = 0;
while (amount < 1000) {
amount *= 2;
days++;
}
Cada passagem dobra a quantidade e conta um dia. Após nove passagens, ela é 512; após dez, é 1024. O teste falso em 1024 deixa days igual a 10. Um laço pode terminar acima de seu limiar quando a atualização avança em passos maiores.
Leia antes de decidir se deve parar
while (true) {
String line = scanner.nextLine();
if (line.equals("stop")) {
break;
}
System.out.println("You wrote: " + line);
}
Aqui scanner é o Scanner de entrada. O laço lê uma linha, verifica se é “stop” e exibe apenas as linhas comuns. O comando de parada é lido, mas não é processado. while (true) precisa de uma saída alcançável para terminar; um laço que continua se repetindo sem sair é um laço infinito.
Registre as alterações de estado
Considere um produto:
int n = 3;
int product = 1;
while (n > 0) {
product *= n;
n--;
}
| Momento | product | n |
|---|---|---|
| Antes do laço | 1 | 3 |
| Após a passagem 1 | 3 | 2 |
| Após a passagem 2 | 6 | 1 |
| Após a passagem 3 | 6 | 0 |
A multiplicação usa o valor anterior de n, e o decremento vem depois. Mover o decremento para antes da multiplicação alteraria os valores multiplicados.
Declare um resultado acumulado antes do laço para que ele seja mantido de uma passagem para outra. Uma variável declarada dentro do corpo é criada novamente sempre que a execução chega à sua declaração. Imprima dentro do corpo para ver os resultados intermediários; imprima após a chave de fechamento para mostrar o resultado final uma vez.
Principais conclusões
- Um laço
whilepode ser executado zero vezes. - Acompanhe a condição antes de cada passagem, incluindo o teste falso final.
- Laços de contagem precisam de uma atualização que avance em direção a um limite de parada.
- Um comando de parada deve ser verificado antes que sua entrada seja processada.
- Mantenha os resultados acumulados fora do corpo do laço.
3.2 Verificações de entrada com do-while
Um laço do-while executa o corpo antes de verificar se outra passagem é necessária. Use-o quando a primeira ação precisar acontecer, como mostrar um menu ou pedir um valor de entrada.
Teste após a primeira ação
int i = 10;
do {
System.out.println(i);
i++;
} while (i < 5);
O corpo imprime 10 e incrementa i para 11. Só então Java testa i < 5. A condição é falsa, portanto não há uma segunda passagem. Um laço while (i < 5) que começasse em 10 não imprimiria nada.
O ponto e vírgula após o while (...) final é obrigatório. Ele encerra a instrução do-while. Isso é diferente do ponto e vírgula acidental após um cabeçalho while com teste no início, que cria um corpo de laço vazio.
Repita enquanto a entrada for inválida
int rating;
do {
System.out.print("Rating (1-5): ");
rating = Integer.valueOf(scanner.nextLine());
} while (rating < 1 || rating > 5);
A solicitação aparece antes da primeira verificação, para que o usuário possa fornecer o valor a ser verificado. Com as entradas 7, depois 0 e depois 4, as duas primeiras avaliações da condição são verdadeiras e provocam outra solicitação. A última é falsa, portanto o laço termina com rating igual a 4.
A condição descreve a continuação, não a aceitação. Uma avaliação válida satisfaz rating >= 1 && rating <= 5. O laço se repete enquanto essa afirmação é falsa, o que as leis de De Morgan reescrevem como rating < 1 || rating > 5. Uma conjunção entre esses limites externos nunca seria verdadeira: um número não pode estar abaixo de 1 e acima de 5 ao mesmo tempo.
Declare a variável verificada antes do bloco
A chave de fechamento encerra o escopo do corpo antes que a condição seja avaliada. Uma declaração como int rating dentro do bloco do ficaria, portanto, indisponível na condição final. Declare-a antes de do e atribua a entrada dentro do corpo. A atribuição sempre é executada antes do primeiro teste.
A mesma posição importa quando o valor aceito é usado depois. rating permanece no escopo após todo o laço e agora contém o último valor lido.
Mantenha um menu aberto
String choice;
do {
System.out.println("a: show status, q: quit");
choice = scanner.nextLine();
if (choice.equals("a")) {
System.out.println("Ready");
}
} while (!choice.equals("q"));
Cada passagem exibe o menu e lê uma escolha. Digitar “a” imprime “Ready” e repete. Digitar “q” pula a ação e encerra o laço na condição. Um comando desconhecido também provoca repetição porque não é “q”.
Quando seu corpo não contém um continue direcionado ao laço, um do-while pode ser reescrito como while (true) com um break no final que verifica a condição negada. Um continue exige cuidado especial nessa reescrita: no do-while original, ele salta para a condição, enquanto em um laço while-true ele salta para o início e pode pular esse teste acrescentado ao final.
Principais conclusões
- O corpo de um do-while é executado antes do primeiro teste.
- O ponto e vírgula final é obrigatório.
- Declare uma variável fora do corpo quando a condição precisar dela.
- Para validação de entrada, repita enquanto o valor for inválido.
3.3 Intervalos e limites do laço for
Um laço for reúne o controle de uma tarefa de contagem em um cabeçalho. Ele é útil quando você conhece o intervalo ou o número de passagens antes do início da repetição.
Leia o cabeçalho na ordem de execução
for (int i = 1; i <= 5; i++) {
System.out.println(i);
}
A inicialização é executada uma vez, definindo i como 1. Java testa i <= 5, executa o corpo se a condição for verdadeira, executa i++ e volta ao teste. A atualização é escrita no cabeçalho, mas é executada depois do corpo. O teste falso final encerra o laço.
Para uma contagem comum, i++ e ++i têm o mesmo efeito na posição de atualização porque o valor de nenhuma das expressões é usado. Mantenha as alterações do contador no cabeçalho para que a sequência seja fácil de prever.
Escolha o primeiro e o último valor
| Cabeçalho | Valores usados pelo corpo | Passagens |
|---|---|---|
int i = 0; i < 5; i++ | 0 a 4 | 5 |
int i = 0; i <= 5; i++ | 0 a 5 | 6 |
int i = 10; i >= 1; i-- | 10 a 1 | 10 |
int i = 0; i <= 20; i += 5 | 0, 5, 10, 15, 20 | 5 |
Para passos crescentes de uma unidade com o final pelo menos igual ao início, um limite final exclusivo produz final menos início passagens; um limite final inclusivo acrescenta uma. Passos maiores exigem listar ou contar os valores efetivamente alcançados. Um laço decrescente deve testar na direção correspondente: começar em 10 com i <= 1 produz zero passagens.
Um erro de uma unidade inclui ou exclui um limite indevidamente. Para imprimir de 1 a 10, i < 10 deixa 10 de fora; use i <= 10. Verifique o primeiro valor do corpo, o último valor do corpo e o primeiro valor que não satisfaz a condição.
Construa um resultado ao longo de um intervalo
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println(sum);
O corpo soma cada inteiro uma vez, terminando com 5050. Um produto começa de forma diferente: inicialize product em 1 antes de multiplicar por 1 a 5. Isso produz 120; começar em 0 manteria o produto em 0 após cada multiplicação.
Observe o escopo e os corpos vazios
Um contador declarado no cabeçalho existe durante todo o laço, mas não depois de sua chave de fechamento. Declare-o antes se o código posterior precisar de seu valor final.
Um ponto e vírgula imediatamente após o cabeçalho é um corpo vazio. Em for (int i = 0; i < 3; i++);, a instrução vazia é executada três vezes. Um bloco seguinte que imprime “Hello” é executado uma vez depois do laço, não três. As chaves devem vir diretamente após o cabeçalho.
Qualquer parte do cabeçalho pode ser omitida. for (;;) { ... } não tem condição de parada e se comporta como while (true); ele precisa de uma saída como break para terminar.
Selecione o laço mais claro
| Tarefa | Forma útil | Motivo |
|---|---|---|
| Percorrer um intervalo conhecido | for | Início, limite e passo ficam juntos. |
| Repetir até uma entrada ou um estado mudar | while | O teste pode impedir a primeira passagem. |
| Perguntar primeiro e depois verificar | do-while | A primeira execução do corpo é obrigatória. |
As formas podem expressar a mesma repetição, mas as reescritas devem preservar a ordem dos testes e das atualizações, incluindo o que um continue pula.
Principais conclusões
- Um laço for executa a inicialização uma vez e depois o teste, o corpo e a atualização.
- Verifique o início, o último valor incluído e a contagem de passagens.
- Um contador declarado no cabeçalho fica indisponível depois do laço.
- Use
forpara intervalos,whilepara mudanças de estado e do-while para uma primeira passagem obrigatória. - Um ponto e vírgula após um cabeçalho for cria um corpo vazio.
3.4 Saídas antecipadas e passagens puladas
Uma saída antecipada pode interromper a repetição assim que sua tarefa estiver concluída. Uma passagem pulada pode deixar de executar um trabalho indesejado enquanto mantém o laço em andamento. Acompanhe seus destinos com cuidado: break e continue têm funções diferentes.
Encerre uma busca com break
for (int n = 51; n <= 100; n++) {
if (n % 7 == 0) {
System.out.println(n);
break;
}
}
Os valores de 51 a 55 não passam no teste de divisibilidade. O próximo valor, 56, é impresso e break sai do laço imediatamente. A atualização não é executada após esse break. Sem ele, múltiplos posteriores como 63 e 70 também seriam impressos.
Um break sem rótulo se aplica ao laço ou switch mais próximo que o contém. A execução continua depois dessa estrutura, não depois do programa inteiro.
Pule com continue
for (int i = 1; i <= 10; i++) {
if (i % 3 == 0) {
continue;
}
System.out.print(i + " ");
}
Para 3, 6 e 9, continue pula a instrução de impressão. Em um laço for, a atualização do cabeçalho ainda é executada, seguida do teste da condição. A saída contém 1, 2, 4, 5, 7, 8 e 10.
Em um while ou do-while, continue vai para a condição. Qualquer atualização abaixo dele no corpo é pulada. Se um contador de while começar em 0 e a primeira ação for if (i % 3 == 0) { continue; }, um i++ posterior no corpo nunca será alcançado. O contador permanece em 0 e o laço se repete para sempre. Mova a atualização necessária para antes de cada caminho que a pula ou use um cabeçalho for para manter a atualização automática.
Saia de laços aninhados deliberadamente
Um break comum dentro de um laço interno encerra apenas esse laço interno. Um rótulo pode indicar um laço externo como destino da saída:
outer:
for (int a = 1; a <= 10; a++) {
for (int b = 1; b <= 10; b++) {
if (a * b == 24 && a + b == 10) {
System.out.println("Found " + a + " and " + b);
break outer;
}
}
}
A busca percorre os pares em ordem. Em a = 4 e b = 6, ambos os testes são satisfeitos e o break com rótulo sai dos dois laços. continue outer seguiria para a atualização do laço externo e depois para seu próximo teste.
Distinga saídas de switch de saídas de laço
Em um laço de menu que contém um switch na forma com dois-pontos, break dentro de um caso encerra o switch. Ele não encerra por si só o laço ao redor. Um padrão claro define uma variável sinalizadora do laço como false no caso de saída e depois usa break para sair do switch. O laço termina quando sua próxima verificação da condição encontra a variável sinalizadora falsa. Casos com seta não precisam de break para impedir a continuação entre casos.
Break sem rótulo é permitido dentro de um laço ou switch; continue é permitido dentro de um laço. Colocá-los em outro lugar causa falha de compilação. Mantenha a regra normal de parada na condição do laço quando ela couber ali. Use while (true) com um break quando o teste de parada naturalmente pertencer a um ponto depois da leitura da entrada, mas antes de seu processamento. Várias saídas podem ser úteis, mas cada caminho adicional acrescenta estado a acompanhar durante o rastreamento.
Principais conclusões
breaksai imediatamente da estrutura à qual se aplica.- O
continuede um laço for ainda executa a atualização do cabeçalho. - O
continuede um laço while pode pular uma atualização necessária do corpo. - Uma saída comum afeta a estrutura válida mais próxima.
- Um break com rótulo pode sair de um laço externo.
- Um break de switch não sai diretamente do laço ao redor.
4Construa e verifique laços úteis
Um laço se torna útil quando mantém apenas as informações de que um problema precisa: uma contagem, uma soma acumulada, um melhor valor ou uma variável sinalizadora que registra uma correspondência. Combinar esses pequenos padrões resolve tarefas de processamento de entrada e de busca. Laços aninhados estendem a repetição a linhas e colunas. Acompanhe os valores que mudam, mantenha o estado no escopo correto e use entradas vazias e casos de valor-limite para verificar se o resultado descreve todos os dados.
4.1 Contagens, somas e médias acumuladas
Um contador registra quantos valores atendem a uma condição. Um acumulador combina valores em um resultado acumulado. Declare ambos antes do laço para que cada passagem continue o trabalho anterior.
Inicialize conforme a operação
Use int count = 0; e incremente quando um item atender à condição. Uma soma começa em 0 e usa sum += value;. Um produto começa em 1, pois multiplicar um 0 inicial eliminaria todos os fatores posteriores. Inicializar um total dentro do corpo o reinicia a cada passagem.
Para um intervalo, o passo do laço pode selecionar os valores: somar os inteiros pares de 2 a 100 em passos de 2 produz 2550. Ou coloque uma condição dentro do laço. Contar os números de 1 a 100 divisíveis por 3 ou por 5 produz 47: os seis múltiplos de 15 devem ser contados apenas uma vez.
Interrompa a entrada antes de somá-la
Uma sentinela é um valor especial de entrada que encerra a leitura. Ela não é um valor comum dos dados:
int sum = 0;
int count = 0;
while (true) {
int number = Integer.valueOf(scanner.nextLine());
if (number == 0) {
break;
}
sum += number;
count++;
}
Para a entrada 12, 7, 5, 0, a soma passa por 12, 19 e 24. A contagem chega a 3. O 0 final aciona o break antes que qualquer uma das variáveis mude. Contá-lo criaria um quarto item e produziria uma média incorreta, embora somar zero não altere a soma.
Divida somente após verificar a contagem
if (count > 0) {
double average = (double) sum / count;
System.out.println(average);
} else {
System.out.println("No numbers entered");
}
O exemplo imprime 8.0. Com operandos inteiros, a divisão descarta a parte fracionária: 25 / 4 é 6. Converta antes de dividir para obter 6,25: (double) sum / count. Fazer a conversão explícita depois, (double) (sum / count), apenas converte o resultado já truncado para 6,0.
Se a sentinela chegar primeiro, a contagem será 0. A divisão inteira por zero lança uma ArithmeticException; uma soma em ponto flutuante igual a zero dividida por zero produz NaN. A verificação da contagem impede que uma entrada vazia produza uma média sem sentido.
Acompanhe vários resultados em uma passagem
Para as pontuações 55, 72, 90, 48 e 81, uma nota mínima de 60 produz cinco pontuações e três aprovações. Mantenha um contador total para cada pontuação e um contador de aprovações dentro da condição de aprovação. 100.0 * passed / total produz 60,0 por cento; 100.0 faz a aritmética usar ponto flutuante. Verifique também se o total é positivo antes dessa divisão.
O local da impressão muda o que é mostrado. Distâncias de 5, 3 e 8 km produzem totais acumulados de 5, 8 e 16 km quando impressos dentro do laço após a adição. Imprimir depois mostra apenas os 16 km finais.
Escolha um tipo grande o suficiente para o total
O máximo de int é 2.147.483.647. Somar todos os inteiros de 1 a 100.000 deve produzir 5.000.050.000, mas um int retorna ao valor 705.082.704 sem informar um erro. long sum = 0; armazena essa soma corretamente; o máximo de long é cerca de 9,2 × 10¹⁸. Fazer uma conversão de ampliação depois de o resultado já ter sofrido estouro não pode recuperar o valor perdido.
Principais conclusões
- Inicialize uma soma ou contagem em 0 e um produto em 1.
- Exclua a sentinela tanto da soma quanto da contagem.
- Converta um operando antes da divisão para preservar a parte fracionária.
- Proteja médias e porcentagens contra uma entrada vazia.
- Mantenha a atualização de cada contador junto à condição que ele conta.
- Use um tipo com capacidade suficiente antes de acumular um total grande.
4.2 Melhores valores, buscas e algarismos
Alguns laços guardam um melhor valor; outros guardam se uma correspondência ocorreu. Escolha o estado inicial de modo que ele represente a situação corretamente antes e depois de cada passagem.
Mantenha o melhor valor encontrado até o momento
Para acompanhar um máximo, substitua-o somente quando o valor atual for maior: if (value > max) { max = value; }. Começando pela primeira leitura, as temperaturas 14, 19, 11, 23 e 17 °C deixam máximos sucessivos de 14, 19, 19, 23 e 23 °C. Um mínimo usa <.
Inicializar um máximo em 0 falha com dados totalmente negativos: -5, -2 e -9 deixariam incorretamente 0 como resultado. Inicialize a partir de uma leitura real ou comece com Integer.MIN_VALUE para um máximo int e Integer.MAX_VALUE para um mínimo int. Informe que não há resultado quando não houver leituras.
Para registrar uma posição, atualize-a no mesmo ramo que o valor. Um > estrito mantém o primeiro máximo em caso de empate; >= o substitui novamente e mantém o último.
Pare após encontrar uma correspondência
int n = 1;
while (n * n <= 500) {
n++;
}
Em 22, o quadrado é 484, portanto outra passagem é executada. Em 23, ele é 529 e a condição falha. O laço encontrou o menor inteiro positivo cujo quadrado é maior que 500. Uma busca com limites pode, em vez disso, testar cada candidato em um laço for e usar break na primeira correspondência.
Para uma pergunta com algum, comece com uma variável sinalizadora falsa e torne-a verdadeira ao encontrar uma correspondência. Para uma pergunta com todos, comece com ela verdadeira e torne-a falsa ao encontrar um contraexemplo. Não reinicie nenhuma das duas em um ramo else para valores posteriores: uma leitura posterior sem correspondência não apaga, por exemplo, uma leitura negativa anterior.
Teste se há um divisor
Um número primo é pelo menos 2 e não tem divisor de 2 até uma unidade a menos que ele mesmo. Para um inteiro positivo pequeno, uma verificação mais curta testa divisores apenas até sua raiz quadrada:
int n = 91;
boolean isPrime = n >= 2;
for (int d = 2; d * d <= n; d++) {
if (n % d == 0) {
isPrime = false;
break;
}
}
Os dois fatores de um par não podem ser ambos maiores que a raiz quadrada. Para 91, o divisor 7 produz resto zero e muda a variável sinalizadora para falsa. Para 97, nenhum divisor de 2 a 9 o divide, portanto a variável sinalizadora permanece verdadeira. Valores abaixo de 2 começam com a variável sinalizadora falsa. Para valores int positivos grandes, use d <= n / d para evitar estouro em d * d.
Remova um algarismo decimal por passagem
Para um inteiro não negativo, % 10 extrai o último algarismo e a divisão inteira / 10 o remove:
int n = 4072;
int sum = 0;
while (n > 0) {
sum += n % 10;
n /= 10;
}
Os algarismos são 2, 7, 0 e 4, produzindo 13. A variável de trabalho n termina em 0. Para inverter os algarismos, atualize reversed = reversed * 10 + n % 10; antes de remover o algarismo; 1234 se torna 4321 quando o resultado cabe no tipo escolhido.
Para contar algarismos, zero precisa de uma passagem mesmo que n > 0 comece falso. Use um do-while que incremente a contagem e divida n por 10. Ele conta um algarismo para 0 e a quantidade habitual para valores positivos.
Principais conclusões
- Inicialize um valor extremo a partir de dados reais ou de um limite adequado do tipo.
- Atualize a posição de um valor extremo junto com seu valor.
- Mantenha uma variável sinalizadora de busca verdadeira após encontrar uma correspondência para “algum” ou falsa após encontrar um contraexemplo para “todos”.
- Um teste de número primo não precisa de divisores acima da raiz quadrada.
- Para inteiros não negativos,
% 10extrai um algarismo e/ 10o remove. - A contagem dos algarismos de zero precisa de uma primeira passagem obrigatória.
4.3 Trabalho aninhado, rastreamentos e casos de teste
Laços aninhados repetem uma repetição inteira a cada passagem externa. Eles são úteis para linhas, colunas, tabelas e formas. O laço interno deve começar novamente sempre que o laço externo chegar a ele.
Imprima uma linha e depois encerre-a
for (int row = 1; row <= 3; row++) {
for (int col = 1; col <= 5; col++) {
System.out.print(row * col + "\t");
}
System.out.println();
}
A primeira linha contém 1, 2, 3, 4, 5; a segunda contém 2, 4, 6, 8, 10; a terceira contém 3, 6, 9, 12, 15. O print interno cria colunas em uma linha; o println após o laço interno encerra essa linha. Mover println para dentro do laço interno coloca cada produto em uma linha própria.
Com contagens fixas, multiplique as passagens externas pelas internas. Três passagens externas e quatro passagens internas executam o corpo interno 12 vezes. A tabela acima tem três vezes cinco, ou 15, impressões de produtos.
Permita que o tamanho da linha mude
for (int row = 1; row <= 4; row++) {
for (int col = 1; col <= row; col++) {
System.out.print("*");
}
System.out.println();
}
O limite interno agora depende da linha. Suas contagens são 1, 2, 3 e 4, portanto o triângulo contém 10 asteriscos. Uma única multiplicação de contagens fixas estaria errada porque o laço interno não é executado o mesmo número de vezes em cada linha.
Use nomes diferentes para contadores de laços cujos escopos se sobrepõem. Declarar outro int i dentro de um laço em que i já está no escopo causa falha de compilação. Para um laço while interno, inicialize seu contador no início de cada passagem externa. Inicializá-lo apenas antes do laço externo o deixa além do limite após a primeira linha.
Rastreie valores em um ponto consistente
Para um laço de 1 a 4, subtraia valores ímpares de um total que começa em 0 e some os pares:
| Valor processado | Ação | Total após a passagem |
|---|---|---|
| 1 | Subtrair 1 | -1 |
| 2 | Somar 2 | 1 |
| 3 | Subtrair 3 | -2 |
| 4 | Somar 4 | 2 |
Registre se uma linha descreve o início ou o fim de uma passagem. Inclua a condição final falsa ao verificar o término. Um rastreamento que misture valores de antes e de depois da atualização pode fazer um laço correto parecer errado.
Coloque separadores entre itens
Cinco números precisam de quatro vírgulas. Imprima um separador antes de cada item, exceto o primeiro:
for (int i = 1; i <= 5; i++) {
if (i > 1) {
System.out.print(", ");
}
System.out.print(i);
}
A saída é “1, 2, 3, 4, 5”, sem vírgula no início ou no fim. Esse é um problema dos postes de cerca: o número de espaços entre itens é diferente do número de itens.
Teste casos que revelam erros
Experimente zero passagens, uma passagem e os valores em cada limite e próximos a ele. Para laços de entrada, experimente a sentinela primeiro. Para laços aninhados, verifique se a segunda linha reinicia corretamente. Impressões temporárias das variáveis de controle do laço revelam o progresso real. Se um programa travar, examine cada caminho em busca de uma atualização ou saída e interrompa-o com Ctrl+C em um terminal ou com o botão de parada do ambiente de desenvolvimento.
Principais conclusões
- O laço interno é executado por completo a cada passagem externa.
- Multiplique as contagens de passagens somente quando ambas forem fixas.
- Reinicie o contador de um while interno a cada passagem externa.
- Coloque a quebra de linha de uma linha após seu laço interno.
- Use um ponto consistente em cada passagem para as linhas da tabela de rastreamento.
- Teste zero passagens, uma passagem e ambos os lados de um limite.
- Separadores ficam entre itens, portanto sua quantidade é uma unidade menor.
Exercícios resolvidos de Condições e laços em Java
1Transforme uma regra do programa em uma condição
12 passos
- 1IntroduçãoComece com uma regra sobre os dados
Uma condição responde a uma pergunta verdadeira ou falsa sobre os dados atuais. Comece com comparações simples e depois combine-as em uma regra que aceite exatamente os valores pretendidos.
Vamos verificar um intervalo de temperatura, comparar texto e proteger uma divisão inteira. Em cada etapa, distinga o significado da condição da ordem em que Java a avalia.
- 2ExplicaçãoDê um nome a uma comparação
Uma comparação produz um
boolean, que pode ser armazenado para uso posterior.int age = 17; boolean isAdult = age >= 18;Aqui
isAdultarmazenafalse. A expressãoif (isAdult)testa esse valor diretamente depois. Um inteiro isolado não pode servir como condição:if (age)falha porque Java exige um booleano, não um número tratado como valor lógico. - 3ExemploLeia o operador com precisão
Com
a = 7eb = 10,a < bé verdadeira ea >= bé falsa. As comparaçõesa != bea == 7são verdadeiras.A diferença entre
=e==importa: a atribuição altera uma variável, enquanto a comparação faz uma pergunta. Para um booleano,if (done = true)compila, mas sobrescreve a variável sinalizadora antes de testá-la. Useif (done)para testar o valor existente. - 4DicaCompare os caracteres da entrada
Uma cadeia de caracteres não nula como
commandtem conteúdo textual e identidade de objeto.command.equals("quit")testa os caracteres;command == "quit"testa a identidade.Use
equalsIgnoreCasesomente quando diferenças entre maiúsculas e minúsculas devam ser aceitas. Por exemplo, “Quit” e “quit” correspondem com esse método, mas são diferentes comequals. Negar uma correspondência exata produz!command.equals("quit"). - 5ExemploVerifique uma diferença decimal
double sum = 0.1 + 0.2; boolean close = Math.abs(sum - 0.3) < 1e-9;A soma é armazenada como
0.30000000000000004. A igualdade exata com0.3é falsa, mas a diferença absoluta está abaixo dessa tolerância, tornandocloseverdadeiro. O teste de tolerância aceita uma pequena diferença; ele não altera nenhum dos valores armazenados nem os torna exatamente iguais. - 6DesafioTeste um número ímpar negativo
Um programa usa
n % 2 == 1para detectar inteiros ímpares. O que ele deixa de identificar quandoné -11 e como o teste pode ser corrigido?---reveal---
-11 % 2é-1, portanto o teste é falso, embora -11 seja ímpar. Usen % 2 != 0: a divisibilidade por 2 tem resto zero, e restos diferentes de zero, positivos ou negativos, identificam inteiros ímpares. - 7ExplicaçãoExija ambos os limites
Para aceitar temperaturas de 18 a 24 °C, exija ambas as comparações:
temp >= 18 && temp <= 24.Com 21, ambas são verdadeiras. Com 17, a primeira é falsa; com 25, a segunda é falsa. Usar
||entre esses limites internos aceitaria os três valores, pois cada um satisfaz pelo menos um dos dois testes. Cada operando deve ser uma expressão booleana completa. - 8Ideia-chaveNegue o intervalo inteiro
Estar fora do mesmo intervalo significa
temp < 18 || temp > 24. Não satisfazer um dos limites é suficiente para estar fora.Esta é a lei de De Morgan em ação:
!(p && q)equivale a!p || !q. Negar ambas as partes também altera o operador que as une. A outra lei é!(p || q)equivale a!p && !q; manter o operador anterior mudaria quais entradas são aceitas. - 9ExemploColoque uma verificação de proteção antes da divisão
int total = 36; int count = 0; boolean large = count != 0 && total / count > 10;A primeira comparação falsa determina o resultado, portanto
&&ignora a divisão. Isso é avaliação de curto-circuito. Inverter os operandos dividiria por zero antes de verificar count e lançaria umaArithmeticException. Com||, um operando esquerdo verdadeiro também faz o direito ser ignorado. - 10DesafioDistinga agrupamento de ordem de leitura
Com
a = true,b = falseec = false,a || b && ce(a || b) && cproduzem o mesmo resultado? Explique o agrupamento.---reveal---
Não. A primeira se agrupa como
a || (b && c)porque&&tem precedência maior, portanto é verdadeira. A segunda exige o resultado dea || be tambémc; comocé falso, esse resultado é falso. - 11DesafioCombine um limite e uma exceção
Uma carga é aceita se estiver entre 6 e 14 kg ou se uma liberação especial estiver ativa, mas um cálculo inteiro
100 / count > 5também deve ser concluído com segurança. Escreva a condição de modo que count igual a 0 não chegue à divisão.---reveal---
count != 0 && (load >= 6 && load <= 14 || override) && 100 / count > 5A primeira verificação de proteção rejeita zero. A escolha agrupada aceita o intervalo ou a liberação especial; apenas um caminho que passe pelas verificações chega à divisão.
- 12RecapitulaçãoVerifique uma condição dos dois lados
Antes de usar uma condição, experimente uma entrada que deve ser aceita e outra que deve ser rejeitada. Para intervalos, verifique também os limites.
Leia os parênteses e a precedência para identificar o agrupamento e depois acompanhe a avaliação de curto-circuito da esquerda para a direita. Isso detecta tanto uma regra de aceitação incorreta quanto um cálculo executado antes de sua verificação de proteção.
2Escolha um caminho e produza um resultado
14 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoAcompanhe o caminho que Java alcança
- 2ExemploExecute exatamente um ramo
- 3ExplicaçãoMantenha o resultado após a decisão
- 4DesafioEncontre uma impressão incondicional
- 5DicaTorne a escolha interna explícita
- 6ExemploPercorra os limiares na ordem correta
- 7ConexãoSepare ações independentes
- 8DesafioCorrija um limite omitido
- 9ExplicaçãoEscolha por um valor exato
- 10ExemploAtribua o valor escolhido
- 11ExplicaçãoForneça seu valor a um bloco
- 12DesafioAcompanhe a continuação entre casos com dois-pontos
- 13DesafioEscolha uma estrutura para uma regra mista
- 14RecapitulaçãoExamine os limites da decisão
3Acompanhe um laço desde a primeira passagem até a saída
18 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoObserve a mudança de estado
- 2ExplicaçãoTeste antes de entrar
- 3ExemploAcompanhe um produto que muda
- 4DesafioEvite pular o valor de parada
- 5ExplicaçãoExecute uma vez antes de decidir
- 6ExemploLeia uma avaliação antes de testá-la
- 7DesafioPreveja um limite aceito
- 8ConexãoLeve a contagem para o cabeçalho
- 9ExemploConte em passos maiores que uma unidade
- 10DesafioMantenha o limite pretendido
- 11DicaVerifique se há um corpo vazio
- 12ExemploPare na primeira correspondência
- 13ExplicaçãoPule o restante de uma passagem
- 14DesafioEncontre a atualização pulada
- 15ExplicaçãoDê um nome de saída a um laço externo
- 16ConexãoDistinga saídas de switch e de laço
- 17DesafioCombine uma passagem pulada e uma saída antecipada
- 18RecapitulaçãoAcompanhe o próximo destino
4Construa resultados que descrevam todos os dados processados
19 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoDecida o que deve ser mantido entre passagens
- 2ExplicaçãoSepare uma contagem de uma soma
- 3ExemploLeia e rejeite a sentinela
- 4ExemploAcompanhe o estado durante a entrada
- 5ExplicaçãoPreserve a parte fracionária da média
- 6DesafioCalcule a média apenas das leituras aceitas
- 7DicaUse capacidade numérica suficiente desde o início
- 8ExemploMantenha a melhor leitura
- 9DesafioRegistre onde ocorre um empate
- 10Ideia-chaveDeixe uma variável sinalizadora registrar uma correspondência
- 11ExplicaçãoBusque um divisor
- 12ExemploExtraia algarismos em uma ordem fixa
- 13DesafioMantenha o registro de uma leitura negativa
- 14ExplicaçãoComplete cada linha antes de avançar
- 15ExemploConte tamanhos de linha que mudam
- 16DesafioAjuste o separador no primeiro item
- 17DicaEscolha linhas de rastreamento reveladoras
- 18DesafioCombine um limite variável com seleção
- 19RecapitulaçãoVerifique o significado de cada resultado
Questões de Condições e laços em Java
Conjunto 1: Acompanhe testes, atualizações e saídas de laços10 Questões de Prática
Questão 1 de 10
Quantas vezes o corpo é executado?
int n = 12;
while (n < 8) {
n++;
}
Mostrar respostaOcultar resposta
Questão 2 de 10
O que é impresso?
int level = 9;
do {
level -= 2;
} while (level > 8);
System.out.println(level);
Mostrar respostaOcultar resposta
Questão 3 de 10
Quantas execuções do corpo ocorrem?
for (int k = 2; k <= 17; k += 4) {
System.out.println(k);
}
Mostrar respostaOcultar resposta
Questão 4 de 10
O que é impresso, ignorando o espaço final?
for (int k = 2; k <= 7; k++) {
if (k % 2 == 0) {
continue;
}
System.out.print(k + " ");
}
Mostrar respostaOcultar resposta
Questão 5 de 10
Quais são os valores de amount e steps após este laço?
int amount = 3;
int steps = 0;
while (amount < 40) {
amount *= 2;
steps++;
}
Mostrar respostaOcultar resposta
Questão 6 de 10
Qual é o valor final de total?
int total = 0;
for (int k = 1; k <= 8; k++) {
if (k % 3 == 0) {
continue;
}
total += k;
if (total > 12) {
break;
}
}
Mostrar respostaOcultar resposta
Questão 7 de 10
Mostrar respostaOcultar resposta
Questão 8 de 10
int index. Onde o código pode ler essa variável?Mostrar respostaOcultar resposta
Questão 9 de 10
O que é impresso?
int hits = 0;
outer:
for (int row = 1; row <= 4; row++) {
for (int col = 1; col <= 4; col++) {
if (row + col == 5) {
break outer;
}
hits++;
}
}
System.out.println(hits);
Mostrar respostaOcultar resposta
Questão 10 de 10
Por que este laço nunca termina?
int n = 1;
while (n != 12) {
n += 2;
}
Mostrar respostaOcultar resposta
Conjunto 2: Leia condições e escolha um caminho10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Por que este código não compila?
int value = 8;
String label;
if (value > 5) {
label = "large";
}
System.out.println(label);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Qual valor é armazenado em mode?
String command = "RUN";
int mode = switch (command) {
case "run" -> 1;
case "wait" -> 2;
default -> 3;
};
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
int sum = 15; e int count = 0;, o que acontece ao avaliar count == 0 || sum / count > 4?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
member && !blocked || guest && codeValid é verdadeiro. Qual condição rejeita exatamente as entradas que ele permitiria?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
-13 % 2 != 0?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
String command não nula contém texto lido da entrada. Qual expressão testa se seu conteúdo é exatamente “pause”?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
O que isto imprime?
boolean ready = true;
boolean locked = false;
boolean expired = false;
System.out.println(ready || locked && expired);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
O que este código imprime?
int stock = 0;
if (stock > 0) {
System.out.print("available ");
} else {
System.out.print("empty ");
}
System.out.print("checked");
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
O que é impresso?
int load = 74;
if (load >= 50) {
System.out.print("medium");
} else if (load >= 70) {
System.out.print("high");
} else {
System.out.print("low");
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 3: Calcule resultados ao longo de entradas repetidas10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
int sum = 17; e int count = 4;, qual é o resultado de (double) (sum / count)?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
max em 0 pode produzir a resposta errada?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
O que é impresso?
int n = 6205;
int sum = 0;
while (n > 0) {
sum += n % 10;
n /= 10;
}
System.out.println(sum);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Quantos asteriscos são impressos no total?
for (int row = 2; row <= 5; row++) {
for (int col = 1; col < row; col++) {
if (col == 2) {
continue;
}
System.out.print("*");
}
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
Quais são os valores de best e position depois?
int best = Integer.MIN_VALUE;
int position = 0;
for (int day = 1; day <= 5; day++) {
int value = day % 3 - 4;
if (value >= best) {
best = value;
position = day;
}
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Qual é a saída?
for (int k = 3; k <= 5; k++) {
if (k > 3) {
System.out.print(", ");
}
System.out.print(k);
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
O que este código imprime?
boolean allPositive = true;
for (int k = 1; k <= 4; k++) {
int value = k - 2;
if (value <= 0) {
allPositive = false;
} else {
allPositive = true;
}
}
System.out.println(allPositive);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 4: Combine decisões com padrões de laços10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
O que é impresso?
int result = 0;
switch (2) {
case 1:
result += 2;
case 2:
result += 3;
case 3:
result += 5;
break;
default:
result = -1;
}
System.out.println(result);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Qual é o valor de total após o laço?
int total = 0;
for (int k = 1; k <= 5; k++) {
switch (k % 3) {
case 0:
break;
default:
total += k;
}
total++;
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Qual é o total final?
int total = 0;
for (int n = 1; n <= 9; n++) {
if (n % 2 == 0) {
total += 2;
} else if (n % 3 == 0) {
total += 3;
} else {
total--;
}
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
do { ... } while (value < 10 || value > 14);. Quantas entradas ele consome?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
O que é impresso?
int n = 58;
int result = 0;
do {
int digit = n % 10;
if (digit % 2 == 0) {
result = result * 10 + digit;
}
n /= 10;
} while (n > 0);
System.out.println(result);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Math.abs((0.1 + 0.2) - 0.3) < 1e-9 pode ser verdadeiro enquanto (0.1 + 0.2) == 0.3 é falso?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
(double) sum / count. Qual é o resultado e qual correção é necessária?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
O que este código imprime?
for (int n = 4; n > 0; n--);
{
System.out.print("done");
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 5: Encontre erros e preveja comportamentos combinados10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
score < 0 || score > 40, depois classifica score >= 30 como “high”, score >= 18 como “middle” e o restante como “low”. Quais classificações as pontuações 40, 41 e 18 recebem, nessa ordem?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
!(false || true)?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
O que é impresso?
int a = -2;
int b = 5;
if (a > 0)
if (b > 0)
System.out.print("both");
else
System.out.print("one");
System.out.print("end");
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
Qual valor é atribuído?
int level = 3;
int result = switch (level) {
case 1, 2 -> 4;
case 3 -> {
int base = level * 2;
yield base + 1;
}
default -> 0;
};
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Qual é o count final?
int count = 0;
outer:
for (int row = 1; row <= 3; row++) {
for (int col = 1; col <= 3; col++) {
if (row == col) {
continue outer;
}
count++;
}
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
n = 143, um laço que verifica se um número é primo começa no divisor 2 e continua enquanto d * d <= n, usando break quando o resto é zero. Em qual divisor ele usa break pela primeira vez?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Qual é o valor de count ao final?
int count = 0;
int col = 1;
for (int row = 1; row <= 3; row++) {
while (col <= row) {
count++;
col++;
}
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
(double) sum / count imprime e qual correção é necessária?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Qual contagem de algarismos isto produz para n = 0?
int n = 0;
int digits = 0;
do {
digits++;
n /= 10;
} while (n > 0);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Travou em uma questão sua? Ajuda com Tarefas
Termos-Chave
A
Acumulador
Atualização
i += 4 move o contador de 2 para 6 depois que a primeira execução do corpo do laço for termina.Avaliação de curto-circuito
&& ou || quando o operando esquerdo já determina todo o resultado.count != 0 && sum / count > 5 segura quando ambas as variáveis são ints.B
Bloco
Busca
C
Cadeia de else-if
Caso extremo
Condição de continuação
Contador
Continuação entre casos
Contraexemplo
D
Divisão inteira
17 / 4, motivo pelo qual um cálculo de média converte primeiro um operando.E
E lógico
&&.Else pendente
Erro de uma unidade
< 12, mas deve incluir 12.Escopo
Estouro
Exaustividade
Expressão switch
Extração de algarismos
% 10, para uso antes que a divisão o remova.I
Inicialização
Instrução break
Instrução break com rótulo
Instrução continue
Instrução continue com rótulo
Instrução yield
Iteração
L
Laço aninhado
Laço com teste no final
Laço do-while
Laço externo
Laço for
Laço infinito
i <= 5 produz um laço infinito, a menos que outro caminho saia dele.Laço interno
Laço while
Leis de De Morgan
Limiar
score >= 30 inclui 30, enquanto score > 30 deixa essa pontuação exata de fora.M
Máximo
Mínimo
N
Negação
!, transformando verdadeiro em falso e falso em verdadeiro sem alterar os dados subjacentes.!command.equals("stop") é verdadeira enquanto o texto inserido for diferente de “stop”.Número primo
O
Operador condicional
?: seleciona um de dois valores de expressão a partir de uma condição booleana, permitindo uma escolha curta entre dois valores.label como “even” ou “odd” de acordo com um teste de resto.Operador de atribuição
= armazena um valor em uma variável; a expressão resultante tem esse valor atribuído, não um resultado de comparação.if (done = true) altera a variável sinalizadora antes da execução do ramo.Operador de igualdade
== compara valores primitivos, mas, em referências a objetos como cadeias de caracteres, testa se os objetos são idênticos.3 == 3.0 porque a conversão numérica torna seus valores iguais.Operador relacional
<= inclui uma pontuação igual ao limite superior de um intervalo permitido.OU exclusivo
^.OU lógico
||.P
Precedência de operadores
a || b && c significar a || (b && c), embora o OU apareça primeiro.Problema dos postes de cerca
R
Ramo
Resto
% após uma divisão inteira; um resto zero identifica um valor divisível pelo divisor.-13 % 2 é -1, portanto testar se o resto é diferente de zero reconhece esse inteiro ímpar.Rótulo de case
S
Saída antecipada
Seletor
command envia o texto “wait” para um caso com esse rótulo exato de cadeia de caracteres.Sentinela
Soma acumulada
T
Tabela de rastreamento
Teste de valor-limite
Tolerância
1e-9 aceita a pequena diferença entre 0.1 + 0.2 e 0.3 neste cálculo.V
Validação de entrada
Valor booleano
true ou false; comparações produzem esse valor, e condições em Java exigem uma expressão desse tipo.isFull se torna verdadeiro quando um recipiente atinge sua capacidade.Variável de controle do laço
Variável sinalizadora
- 1Primeiros programas em Java
- 2Condições e laços em Java
- 3Métodos em Java
- 4Listas e vetores em Java
- 5Classes e objetos em Java
- 6Objetos e referências em Java
- 7HashMaps e coleções em Java
- 8Herança, interfaces e polimorfismo em Java
- 9Exceções em Java
- 10Pacotes e testes unitários em Java
- 11Genéricos e expressões lambda em Java
Sobre esta aula
Crie seus próprios Materiais de Estudo
Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.