Sintáxe estranha no java

10 respostas
jeanlopes1

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

10 Respostas

A

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?

davidbuzatto

A sintaxe de sintáxe está errada :D

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

Exemplo:
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;

    }

}
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:
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();
    }

}
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:
public static void teste() {

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

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

    System.out.println( "x" );

}
[]´s
jeanlopes1

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!

rmendes08

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;
}
drigo.angelo

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)

rmendes08

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;
}
jeanlopes1

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

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);
rmendes08

Nesse caso, basta usar um continue!

jeanlopes1

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

sergiolopes

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;
Criado 29 de dezembro de 2010
Ultima resposta 4 de jan. de 2011
Respostas 10
Participantes 6