Comando case

boa tarde a todos

estou com uma dúvida sobre um exercício que estava fazendo
é o seguinte:

What all gets printed when the following program is compiled and run. 

public class test {
   public static void main(String args[]) { 
      int i, j=1;
      i = (j>1)?2:1;
      switch(i) {
        case 0: System.out.println(0); break;
        case 1: System.out.println(1);
        case 2: System.out.println(2); break;
        case 3: System.out.println(3); break;
      }
   }
}

a) () 0
b) (X) 1
c) () 2
d) () 3

no gabarito diz que as respostas “b” e “c” são as corretas então pergunto:

concordo que no “case 1” não tem a instrução break e por isso vai ser feito o “case 2”, mas esta certo executar o novo print sendo que o valor de “i” não foi alterado e continua como 1

desde já agradeço

O gabarito está correto. Sairia apenas “1” se você colocasse um break após System.out.println(1);

Faça um teste. Crie a classe e rode, é a melhor maneira de gravar na sua memória.

Sim, esta correto pois o switch-case só começa quando encontra o valor de i (1 nesse caso), e só para com uma instrução break.

(particularmente, gostaria que o case fosse que nem o case do bash, ou que suportasse expressões regulares, mas sem a necessidade do break)

roger concordo que como depois da linha System.out.println(1); não tem o break vai continuar executando os cases.

mas a linha System.out.println(2); não deveria ser executada só se “i” fosse 2, pois o “case 2:” não “testa” se i = 2 ?

Depende da vontade de quem te pediu pra fazer esse programa. Realmente, pra este programinha simples, não faz muito sentido mesmo. Mas para este exercício, a semântica não vem ao caso. Ele só quer mesmo é fazer que você entenda a “anatomia” de um switch.
Quer ver um caso que faz mais sentido não ter o break?

public int getDiasMes(int mes, int ano){
	int resultado;
	switch(mes) {
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			resultado = 31;
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			resultado = 31;
			break;
		case 2:
			if(ehAnoBissexto(ano))
				resultado = 29;
			else
				resultado = 28;
			break;
		default:
			resultado = 0;//Indica erro
	}
	return resultado;
}

De uma lida nesse método. Se tiver dúvidas, pergunte.
Só uma curiosidade: Em C#, esse tipo de coisa (case sem break e case sem break nem return), não compila. C# não permite isso (bleargh…)

Mantu, acho que não estou explicando a minha dúvida direito.
entendi o código que vc postou, mas no seu método os cases (1,3,5,7,8,10 e 12) executarão a mesma instrução.

No meu código (tirado de um exercício de um simulado para certificação) existe as instruções entre os cases.

public class test {
    public static void main(String args[]) { 
       int i, j=1;
       i = (j>1)?2:1;
       switch(i) {
         case 0: System.out.println(0); break;
         case 1: System.out.println(1);
         case 2: System.out.println(2); break;
         case 3: System.out.println(3); break;
       }
    }
 }

não entendo por que executa “System.out.println(2);”
segue meu raciocínio (o problema pode estar ai…rs)

O programinha esta rodando e antes de entrar no bloco switch “i = 1”
ai testa i = 0 (falso)
teste i = 1 (verdadeiro) executa “System.out.println(1);” não tem o break;(então não sai do bloco switch e vai fazer o novo teste)
testa i = 2 (é aqui neste ponto que esta a dúvida, pois se i = 1 pq que executa a instrução do case 2)

desde já agradeço pela paciência

Aqui é onde está o engano. uma vez encontrado um case que satisfaça a condição do switch, os demais cases não são verificados novamente. É como (eu disse: É COMO) se, no seu caso, depois de a condição bater com o “case 1”, o código fosse reescrito para algo assim:

public class test {
     public static void main(String args[]) { 
        int i, j=1;
        i = (j>1)?2:1;
        switch(i) {
          case 0: 
               System.out.println(0); 
               break;
          case 1: 
               System.out.println(1);
               System.out.println(2); 
               break;
          case 3: 
               System.out.println(3); 
               break;
        }
     }
  }

O seu raciocínio se engana ao achar que, depois de encontrado um case que satisfaça a condição, outros cases que aparecerem pelo caminho serão testados novamente com a condição. Isso não ocorre.

agora sim!!!

como eu previa o erro estava no meu raciocínio…

obrigado pelo esclarecimento e pela paciência

Eu acho que deveria ser assim, cada case com seu case e pronto.

Quando encontrar o case 1: deveria executar até encontrar outra palavra case e zé fini. Ora, o case é igual a 1 e não a igual a 2, nunca deveria ter executado o case 2.

Caso tenha que ser executado mais de um case como no exemplo dos meses, bastaria fazer:


switch(mes) {
case 1,3,5,7,8,10,12:
      System.out.prinlnt('31 dias');
case 4,6,9,11:
      System.out.println('30 dias');
case 2:
      System.out.println('É fevereiro que depende das 6h a mais durante 4 anos...e etc..... ');
default:
      System.out.println('Nehum....');
}

Ou assim:


switch(i) {
  case 0: 
      System.out.println(0); 
  case 1: 
      System.out.println(1);
  case 2: 
      System.out.println(2); 
  case 3: 
      System.out.println(3);
}

Se o case é um aninhamento de ORs então nunca deveria ter executado o case 2:.

Sinceramente não sei por que implementaram com o uso explícito do brake nesse caso.

Obs.: Mantu o seu exemplo ainda tem um erro…heheheh…

Qual dos exemplos?

De fato, no caso que eu citei, dos meses, vc tem razão. daria pra fazer o case separando os valores de comparação com vírgula. Esse foi só um exemplo didático. Mas, e se você tem uma situação em que se a condição “CND” for igual a “J” (seja lá o que for A), vc quer executar “Z”, e se a condição for “K”, você quer executar “X” e “Z”, nesta ordem?
Ao invez de fazer:

switch(CND){
   case A:
      ...
      break;
   case B:
      ...
      break;
   ...
   case K:
      X;
      Z;
      break;
   case J;
      Z;
      break;
   ...
}

Você poderia fazer isso:

switch(CND){
   case A:
      ...
      break;
   case B:
      ...
      break;
   ...
   case K:
      X;
   case J;
      Z;
      break;
   ...
}

Nunca parei pra pensar se há alguma saída alternativa melhor para isso. Acho que por comodismo, hehehe…

Heheh, Mantu, seu exemplo retorna 31 dias para os meses 4,6,9 e 11.
Só isso. :smiley:

Sobre o restante do tópico, é, escrever-se-ia menos, mas se implementaram assim é por que foi testado e aprovado né, quem sou eu pra dizer que não está da maneira mais correta.

Eu só gostaria de saber por que no C# esse tipo de construção foi proibida…