Labeled loops

Pessoal,

Estou começando a aprender Java agora apesar de já estar na estrada durante 18 anos… smepre programando e desenvolvendo sistemas em diversas linguaguages… espero que vcs me ajudem no decorrer de meu aprendizado e no futuro tb poder colaborar com vcs!

A minha dúvida é a sequinte:

como usar “labeled loops”

Muito obrigado

:?: O que diabos é isso :?: :lol:

1 curtida

Um exemplo simples:

FINDBIGGER:

for (i = 0; i < max1; i++)
{
	for (j = 0; j < max2; j++)
	{
		if ( array[i] > array[j] )
			break FINDBIGGER;
		else if ( array[i] < array[j] )
			break;
	}
	System.out.println("The break will end up here!");
}
System.out.println("The break FINDBIGGER will end up here!");
1 curtida

Exemplo:
http://www.java2s.com/Code/Java/Language-Basics/Javalabeledforloop.htm
Dá uma caçada no google que tem diversos exemplos como esse.

Cara esse é um recurso que existe mas que não deve ser usado (assim como o GOTO na linguagem C).
Um exemplo do uso de labeled loop vai a seguir:

public class LabeledFor {

  public static void main(String[] args) {
    int i = 0;
    outer: // Can't have statements here
    for(; true ;) { // infinite loop
      inner: // Can't have statements here
      for(; i < 10; i++) {
        System.out.println("i = " + i);
        if(i == 2) {
          System.out.println("continue");
          continue;
        }
        if(i == 3) {
          System.out.println("break");
          i++; // Otherwise i never
               // gets incremented.
          break;
        }
        if(i == 7) {
          System.out.println("continue outer");
          i++; // Otherwise i never
               // gets incremented.
          continue outer;
        }
        if(i == 8) {
          System.out.println("break outer");
          break outer;
        }
        for(int k = 0; k < 5; k++) {
          if(k == 3) {
            System.out.println("continue inner");
            continue inner;
          }
        }
      }
    }
    // Can't break or continue to labels here
  }
} ///:~

Os labeled loops servem quando você tem laços aninhados e quer fazer um desvio do fluxo de execução (através de um break ou de um continue). Desta forma você nomeia o laço (label: antes do bloco do laço) e quando for realizar o desvio no fluxo da execução (break ou continue) o nome do laço para o qual o fluxo deverá ser desviado deve ser informado.

1 curtida

Hahahahaha, fomos no mesmo link :smiley:
Lembro que saiu na javaworld a um tempão um artigo descrevendo em detalhes os labeled loops e outras construções esquisitas da linguagem java. Porém fiz uma busca rápida no javaworld e não encontrei esse artigo.

[quote=brunogamacatao]Cara esse é um recurso que existe mas que não deve ser usado (assim como o GOTO na linguagem C).
Um exemplo do uso de labeled loop vai a seguir:

public class LabeledFor {

  public static void main(String[] args) {
    int i = 0;
    outer: // Can't have statements here
    for(; true ;) { // infinite loop
      inner: // Can't have statements here
      for(; i < 10; i++) {
        System.out.println("i = " + i);
        if(i == 2) {
          System.out.println("continue");
          continue;
        }
        if(i == 3) {
          System.out.println("break");
          i++; // Otherwise i never
               // gets incremented.
          break;
        }
        if(i == 7) {
          System.out.println("continue outer");
          i++; // Otherwise i never
               // gets incremented.
          continue outer;
        }
        if(i == 8) {
          System.out.println("break outer");
          break outer;
        }
        for(int k = 0; k < 5; k++) {
          if(k == 3) {
            System.out.println("continue inner");
            continue inner;
          }
        }
      }
    }
    // Can't break or continue to labels here
  }
} ///:~

Os labeled loops servem quando você tem laços aninhados e quer fazer um desvio do fluxo de execução (através de um break ou de um continue). Desta forma você nomeia o laço (label: antes do bloco do laço) e quando for realizar o desvio no fluxo da execução (break ou continue) o nome do laço para o qual o fluxo deverá ser desviado deve ser informado.[/quote]

Como assim não deve ser usado?

Se vc tem 10 salas e em cada sala 10 armários com 5 gavetas cada 1 e está procurando um mapa que só vai estar em uma gaveta de um armário de uma sala. Como vc faria?

Pq no momento q vc achar o mapa, pode parar de procurar nas outras gavetas, armários e salas…

É o tipo de coisa que deve ser usada sim, para evitar aqueles famosos “try/catch” que o pessoal usa para sair fora de mais de um nível de loop.

(Já vi muito isso porque não conheciam labeled loops, e essa construção não existe no C++, C# e várias outras linguagens).

Em C# você tem de usar goto (isso mesmo!) ou try/catch para ter o mesmo efeito de um “labeled loop”.

Não aconselho usar flags para obter o mesmo efeito de um “labeled loop”. Cada flag que você inclui em um programa torna-o mais difícil de testar.

Pessoal,

Obrigado pela resposta… andei pesquisando e descobri que esse rotulo tb pode ser usado no while, nao apenas no for e que para quem vai fazer teste de certificação essa questão é quase certa de cair.

“As instrucoes break e continue em vários níveis remove a justificativa que ainda restava para a infame instrução goto do C/C++”

Patrick Niemeyer - do livro Aprendendo Java

Muito Obrigado

[quote=thingol]É o tipo de coisa que deve ser usada sim, para evitar aqueles famosos “try/catch” que o pessoal usa para sair fora de mais de um nível de loop.

(Já vi muito isso porque não conheciam labeled loops, e essa construção não existe no C++, C# e várias outras linguagens).

Em C# você tem de usar goto (isso mesmo!) ou try/catch para ter o mesmo efeito de um “labeled loop”.

Não aconselho usar flags para obter o mesmo efeito de um “labeled loop”. Cada flag que você inclui em um programa torna-o mais difícil de testar.

[/quote]
Thingol, sem querer abusar, mas já abusando:

Nesse tipo de situação não existe uma forma mais legível de se obter o mesmo resultado? Nem que isso traga um desempenho inferior ou exija que chamemos um maior número de métodos.

Achei os exemplos postados muito sintéticos, então não entendi direito o codigo try/catch gambiarral que você citou.

Ou os casos de uso dos labeled loops são casos bem atípicos ou de algoritmos super lentos que precisam de toda e qualquer otimização?

Tem gente que usa “return” (e acrescenta um método) para sair de dois ou mais níveis de loop, mas isso costuma ser barrado por gente que acredita que todo método deve ter apenas um ponto de saída. (Se você vai fazer código para o Bradesco, todo método deve ter apenas um return, no máximo.)

O “try/catch” gambiarral que eu citei tem efeito semelhante, mas causa muitos problemas de desempenho. Além disso, pode mascarar um erro real.

try {
    while ( loop 1 ) {
        while ( loop 2 ) {
            if ( cond 3 ) {
                throw new ControleDeFluxoException();
            }
       }
    }
} catch (ControleDeFluxoException ex) {
}

Pattern: use try/catch quando tiver algum erro/exceção para tratar.
Anti-pattern: nunca use try/catch para controle de fluxo.

Uma situação interessante é quando se tem um switch dentro de um loop e você quer dar um break no loop mas de dentro do switch. Como o break nesse caso vai sair apenas do switch, você poderia rotular o loop e dar um “break rotulo”…

[quote=thingol]É o tipo de coisa que deve ser usada sim, para evitar aqueles famosos “try/catch” que o pessoal usa para sair fora de mais de um nível de loop.

(Já vi muito isso porque não conheciam labeled loops, e essa construção não existe no C++, C# e várias outras linguagens).

Em C# você tem de usar goto (isso mesmo!) ou try/catch para ter o mesmo efeito de um “labeled loop”.

Não aconselho usar flags para obter o mesmo efeito de um “labeled loop”. Cada flag que você inclui em um programa torna-o mais difícil de testar.

[/quote]

Concordo em gênero, número e grau, com o Thingol, não tem pq não usar, o código fica mais limpo e facil de testar, diminui o trabalho tambem de ficar trabalhando com flags.

Muito boa explicação, gostei. Entao entendo que posso colocar quantos Ifs eu achar necessário. Obrigado :oops: