Sintáxe estranha no java

Gente, é uma dúvida simples de ser respondida, mas não sei como se chama isso. Deve ser algo relacionado a escopo, mas não sei o nome, nem como usar ou porque usar…

umaPalavra : {

         aqui vai código normal...

                   }

isso lembra um pouco a sintaxe do JSON, mas não a entendo no contexto de orientação a objetos. Se alguém souber explicar… =D

Onde estava inserido esse código?

Pelo que me parece o “umaPalavra :” é um label, que geralmente você usa em conjunto com breaks. (Aliás, geralmente você não usa isso!)

As chaves são apenas para delimitar um bloco de código, um “sub-escopo” dentro do escopo atual.

Este trecho de código estava dentro de um método?

A sintaxe de sintáxe está errada :smiley:

Brincadeiras à parte, “umaPalavra” é um label, que é usado para sair de loops aninhados.

Exemplo:

[code]int x = 10;

labelWhile:
while ( x-- > 0 ) {

for ( int i = 0; i < 10; i++ ) {

    System.out.println( i + x );
    
    // quanto i + x for igual a 5, quebra o while, não o for.
    if ( i + x == 5 )
        break labelWhile;

}

}[/code]
Em C, por exemplo, um label é usado como parâmetro para um goto. Em Java a utilidade dos labels é justamente a que disse, ou seja, quebrar (break) loops aninhados ou mesmo dar um continue.

O código entre chaves é um bloco. Você pode criar quantos blocos quiser. Existem blocos normais (como você escreveu) e blocos estáticos. Blocos normais, quando inseridos fora de métodos, são executados em ordem quando um objeto de uma determinada classe é instanciado. Blocos estáticos são executados, também em ordem, durante a carga da classe. Exemplo:

[code]public class Teste {

static {
    System.out.print( "a" );
}

{
    System.out.print( "b" );
}

public static void teste() {
    System.out.print( "c" );
}

public static void main( String[] args ) {
    new Teste();
    new Teste().teste();
    System.out.println();
}

}[/code]
Saída: abbc. O “a” é exibido assim que a classe Teste é carregada. Ao criar um objeto do tipo Teste, o primeiro bloco normal é executado, exibindo então um “b”. Ai cria-se mais um objeto, novamente o bloco normal é executado, só que dessa vez, é chamado o método teste do objeto, exibindo então “c”, que por sua vez poderia estar dentro de um bloco. Os blocos são usados principalmente para separar o escopo de variáveis. Quando você declara uma variável dentro do bloco de um for por exemplo, aquela variável só existe naquele escopo. Mais um exemplo:

[code]public static void teste() {

{
    int x = 10;
    System.out.println( x );
}

{
    int x = 12;
    System.out.println( x );
}

System.out.println( "x" );

}[/code]
[]´s

Hehe, legal… nem tinha me dado conta que não ia acento lá…

bom, graças ao davidbuzatto fui me dar conta de pra que serve… Ele escreveu a label para parar um laço específico quando muitos estão alinhados e para delimitar escopo de variáveis. Ok, esta primeira eu não conhecia mesmo.

Mas o interessante é que a sintaxe do código originalmente postado serve para parar trechos de código, mesmo que não pertençam a laços.

Por exemplo

public void setString(String string) { umaPalavra : { if (string.equals("string")) { JOptionPane.showMessageDialog(null, "vc escreveu" + string); break umaPalavra; } if (string.equals(".*?")) JOptionPane.showMessageDialog(null, "vc escreveu" + string); } this.string = string; }

quando é dada a instrução break umaPalavra ele nem lê o próximo if… interessante se você quer se livrar do return para não ter que parar o método inteiro e nem ter que lançar uma exceção…

Vlwww a todos os que responderam!

Não, não é interessante e particularmente eu não incentivo esse uso. É o tipo de coisa que pode ser muito bem resolvido estruturando corretamente o código. Um break para simplificar a condição de parada de um laço é aceitável, mas na grande maioria das vezes desvios incondicionais somente servem para deixa o código obscuro. Esse método fica muito melhor assim:

public void setString(String string) {  
	if (string.equals("string")) { 
		JOptionPane.showMessageDialog(null, "vc escreveu" + string);  
	}else if (string.equals(".*?")){
		JOptionPane.showMessageDialog(null, "vc escreveu" + string);
	}

	this.string = string;
}

Concordo com rmendes08…

eu particularmente não gosto de breaks nem pra sair de loops( a não ser quando estritamente necessário, por questões de performance)

Um exemplo de quando eu acho interessante usar break/return:

public Cliente encontrarJoaoDaSilva(){
    Cliente [] cliente = ClienteDao.leClientesDoBanco();

     for(Cliente c : cliente){
         if("João da Silva".equals(c.getNome()))
             return c;
     }
}

ao invés de :

public Cliente encontrarJoaoDaSilva(){
    Cliente [] cliente = ClienteDao.leClientesDoBanco();

    Cliente joaoDaSilva = null;

     for(int i = 0 ; i < cliente.length && joaoDaSilva == null ; i++){
         if("João da Silva".equals(cliente[i].getNome()))
             joaoDaSilva = cliente[i];
     }

     return joaoDaSilva;
}

Cara, não estou propondo aquele break para deixar o código obscuro. Aquilo, apesar de não ser o melhor exemplo, serve para ilustrar como usar tal fenômeno que o java permite.

Acho que para questões de performance aquele break label sem loops muito útil. Vou dar um exemplo melhor de uso

[code]private Object parseIt(Object mOrL) {
String oldString;
int i = 0;
long countTags = 0;
do {
oldString = this.string;

        parseamento:
        {

            Pattern endTag = Pattern.compile("<.+?/>");
            Matcher et = endTag.matcher(string);
            if (!this.closeTag.empty() && et.find() && et.group(0).equals("<" + this.closeTag.peek().toString() + "/>")) {
                this.closeTag.pop();
                string = et.replaceFirst("");
                return (Map<String, Object>) mOrL;
            } else if (!this.closeTag.empty() && et.find() && !et.group(0).equals(this.closeTag.peek())) {
                controlador.printOnLog("Erro de sintaxe "
                        + "no xml. Por favor,\n passe-o em um validador"
                        + "\n a tag " + et.group(0) + " está fechando uma tag que não foi aberta"
                        + "\nArquivo:" + actualFile
                        + "Tag nº:" + String.valueOf(countTags));
                throw new IllegalArgumentException();
            }




            Pattern shortTag = Pattern.compile("<.+?/>");
            Pattern longTag = Pattern.compile("<.+?</");

            Matcher sT = shortTag.matcher(this.string);
            Matcher lT = longTag.matcher(this.string);

            if (sT.find() && lT.find() && sT.end() < lT.end()) {
                countTags++;
                this.string = sT.replaceFirst("");
                String aux = sT.group(0);
                Pattern tag = Pattern.compile("<.+? ");
                Matcher t = tag.matcher(aux);
                if (!t.find()) {
                    controlador.printOnLog("Erro de sintaxe "
                            + "no xml. Por favor,\n passe-o em um validador"
                            + "\nArquivo:" + actualFile
                            + "Tag nº:" + String.valueOf(countTags));
                    throw new IllegalArgumentException();
                }
                aux = t.replaceFirst("");

                Pattern pairs = Pattern.compile(".+?\"=\".+?\"");
                Matcher p = pairs.matcher(aux);
                ArrayList allP = new ArrayList();
                if (p.find()) {
                    for (int j = 0; j < p.groupCount(); j++) {

                        Pattern k = Pattern.compile("\".*?\"=");
                        Matcher n = k.matcher(p.group(j));
                        n.find();
                        String key = n.group();
                        key = key.substring(1, key.length() - 3);

                        String value = n.replaceFirst("");
                        value = value.substring(1, value.length() - 2);
                        allP.add(new HashMap<String, String>().put(key, value));
                    }
                }
                ((Map<String, Object>) mOrL).put(t.group(0), allP);
            }



            if (sT.find() && lT.find() && sT.end() > lT.end()) {
                countTags++;
                Pattern tag = Pattern.compile("<.+?>");
                Matcher t = tag.matcher(lT.group(0));
                if (!t.find()) {
                    controlador.printOnLog("Erro de sintaxe "
                            + "no xml. Por favor,\n passe-o em um validador"
                            + "\nArquivo:" + actualFile
                            + "Tag nº:" + String.valueOf(countTags));
                    
                    





                    //throw new IllegalArgumentException();
                    // aqui, ao invés de parar o método com uma exception, podemos parar apens o trecho de instrução 
                    //até o final do loop corrente, sem parar nem ao menos o loop por inteiro. Útil não?
                    break parseamento;








                }

                t = tag.matcher(string);
                t.find();
                string = t.replaceFirst("");
                String key = t.group(0).substring(1, t.group(0).length() - 2);
                closeTag.push(key);

                Pattern tagFirst = Pattern.compile("<[A-Za-z-]|[0-9-]");
                Pattern textFirst = Pattern.compile("[A-Za-z-]|[0-9-]<");

                Matcher tagf = tagFirst.matcher(string);
                Matcher textf = textFirst.matcher(string);

                if (tagf.find() && textf.find() && tagf.start() < textf.start()) {
                    ((Map<String, Object>) mOrL).put(key, this.parseIt(new HashMap<String, Object>()));
                } else if (tagf.find() && textf.find() && tagf.start() > textf.start()) {
                    textFirst = Pattern.compile(".+?<");
                    textf = tagFirst.matcher(string);
                    textf.find();
                    string = textf.replaceFirst("");
                    string = "<" + string;
                    ((Map<String, Object>) mOrL).put(key, textf.group(0).substring(0, textf.group(0).length() - 2));
                }

            }


        }
        i = oldString.equalsIgnoreCase(this.string) ? i + 1 : 0;
    } while (i < 5);[/code]

Nesse caso, basta usar um continue!

Não.

Há uma instrução dentro do loop while e fora do escopo de label parseamento que precisa ser executada. Ela não seria executada se desse um continue pq isso faria o while partir pro próximo loop.

Instrução que não seria executada: linha 129 i = oldString.equalsIgnoreCase(this.string) ? i + 1 : 0;

Entendeu? Então se os ilustres inventores do java permitiram essas coisas (que eu ainda não sei o nome ¬¬) foi por um motivo inteligente. Acho que nada da sintaxe do java está em desuso!!

=D

Essa bizarrice se chama Labeled Statements. Na verdade os Labeled Loops são um caso “particular” desse fenômeno maior.

Na prática, não é uma boa ideia usar esses labels. Mesmo em loops (o único caso razoável) é recomendado bastante cuidado ao usar. Já colocar labels em outras coisas é pura bizarrice mesmo.

Mas dão uns códigos divertidos :slight_smile:

syso: System.out.println("Oi");

ou

meubreak: break meubreak;