Existe uma instrução goto em Java?

259

Estou confuso sobre isso. Muitos de nós já foram informados de que não existe nenhuma declaração goto em Java.

Mas descobri que é uma das palavras-chave em Java. Onde isso pode ser usado? Se não pode ser usado, por que foi incluído no Java como uma palavra-chave?

Venkat
fonte
13
apenas uma palavra de conselho: nunca usar goto
lostiniceland
16
E depois há "'Ir para a declaração considerada prejudicial' considerado prejudicial" e "'" Ir para a declaração considerada prejudicial "Considerado prejudicial' considerado prejudicial?" VEEEEERY recursivo, esse meme.
Chris Charabaruk
70
'goto' é sempre mau - como em 'goto work' ou 'goto school';)
Andreas Dolk
24
A verdadeira razão é que a palavra "g ** o" é considerada obscena na maioria das linguagens de programação. Os designers de Java estão apenas protegendo jovens programadores inocentes de influências corruptas. (:-))
Stephen C
25
A caça às bruxas contra o goto gerou alguns dos momentos mais agravantes da minha vida. Eu já vi pessoas contorcendo código C ocultando funcionalidade em funções, colocando lógica de saída absurda em loops multi-aninhados e, de outra forma, fazem todas as formas de engenharia excessivamente imaginável APENAS para evitar alguém criticar seu código em uma revisão de código. Esta regra, juntamente com o canard "você deve evitar múltiplos retornos", é impregnada de absurdos. Há momentos em que o goto torna as coisas menos sustentáveis. Há momentos em que o goto torna as coisas mais fáceis de manter. Eu esperava que essa caça às bruxas tivesse morrido nos anos 80.

Respostas:

200

A lista de palavras-chave Java especifica a gotopalavra - chave, mas está marcada como "não usada".

Ele estava na JVM original (veja a resposta por @VitaliiFedorenko ), mas foi removido. Provavelmente foi mantida como uma palavra-chave reservada, caso fosse adicionada a uma versão posterior do Java.

Se gotonão estivesse na lista e depois fosse adicionado ao idioma, o código existente que usava a palavra gotocomo identificador (nome da variável, nome do método, etc ...) seria interrompido. Mas, como gotoé uma palavra-chave, esse código nem será compilado no presente, e ainda é possível fazê-lo realmente fazer algo mais tarde, sem quebrar o código existente.

Thomas
fonte
29
This was probably done in case it were to be added to a later version of Java.Na verdade, a principal razão é um pouco diferente (veja minha resposta abaixo) #
Vitalii Fedorenko
2
Essa é uma informação boa e interessante, mas não explica por que ainda é uma palavra-chave reservada.
Thomas
@ Thomas Você não descreveu por que é reservado? É uma palavra-chave, portanto não pode ser usada agora; mais tarde, poderá saltar para a vida sem causar problemas. Se não fosse uma palavra reservada, poderia ser usada agora para produzir código (int goto = 2;) que seria quebrado se o goto fosse introduzido.
230

James Gosling criou a JVM original com suporte a gotoinstruções, mas depois removeu esse recurso como desnecessário. O principal motivo gotoé desnecessário: geralmente, ele pode ser substituído por instruções mais legíveis (como break/continue) ou pela extração de um pedaço de código em um método.

Fonte: James Gosling, sessão de perguntas e respostas

Vitalii Fedorenko
fonte
24
"... ou extraindo um pedaço de código em um método" - isso deve ser muito legal sem a eliminação adequada da chamada final.
Exibir nome
45
Às vezes, o uso criterioso de goto é a maneira mais fácil e clara de expressar algo; portanto, forçá-lo a qualquer outra coisa é menos legível .
Deduplicator
1
@Duplicator O uso do goto, por mais criterioso que seja, sempre está sujeito a erros.
Çelebi Murat
@Duplicador O único uso de goto considerado uma boa prática em C ++ é apoiado pela interrupção / continuação.
Inverno
2
Ir para ser uma palavra-chave reservada em Java é ótimo porque impede as pessoas de nomear rótulos "goto:".
Inverno
147

A palavra-chave existe, mas não está implementada.

A única boa razão para usar o goto em que consigo pensar é:

for (int i = 0; i < MAX_I; i++) {
    for (int j = 0; j < MAX_J; j++) {
        // do stuff
        goto outsideloops; // to break out of both loops
    }
}
outsideloops:

Em Java, você pode fazer o seguinte:

loops:
for (int i = 0; i < MAX_I; i++) {
    for (int j = 0; j < MAX_J; j++) {
        // do stuff
        break loops;
    }
}
jonnystoten
fonte
1
@ Zoltán No - redireciona o código para a etiqueta, logo antes do primeiro loop.
assylias 16/05
21
@assylias Bem, não exatamente. O rótulo identifica o loop externo. Então break loopssignifica "sair do loop chamado loops". Talvez, em retrospecto, um nome melhor para o rótulo possa ter sido outer.
21812 jonnystoten
8
"A única boa razão para usar o goto" Pequenos programas rápidos e sujos que precisam de um loop infinito incondicional fazem bom uso do goto. Usar while (true) {... }é um exagero. O GOTO é frequentemente estigmatizado por seus usos impróprios, mas eu argumento que comparações desnecessárias com literais booleanos são piores que o GOTO.
Alexander - Restabelecer Monica
1
O rótulo dos loops não deveria estar após os loops?
GC_
1
Descobri recentemente que essa técnica de rotulagem também é muito útil em combinação com uma continue LABEL;declaração. Assim, você pode continuar um loop externo.
Infotoni91 21/03/19
43

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html

"As palavras-chave const e goto são reservadas, mesmo que não sejam usadas no momento."

Isaac E
fonte
12
"não assinado" nem está lá! (Suspiro)
Matthieu
Faz sentido, pois todos os tipos primitivos em Java são assinados.
mwieczorek
1
@mwieczorek Nem todos. "char" é um tipo primitivo e não está assinado.
Sergey Krivenkov
29

Então eles poderiam ser usados ​​um dia se os designers de idiomas sentissem a necessidade.

Além disso, se programadores de linguagens que possuem essas palavras-chave (por exemplo, C, C ++) as usam por engano, o compilador Java pode fornecer uma mensagem de erro útil.

Ou talvez fosse apenas para parar os programadores usando goto :)

Dave
fonte
A funcionalidade goto ausente em Java deve ser motivo suficiente para não usar goto - não há necessidade de reservá-la como uma palavra-chave. A seguir, você lógica, tudo seria uma palavra-chave, uma vez que é usada tanto por outras línguas e / ou os designers Java poderia usá-lo no futuro ...
Stuxnet
1
Eu não acho que minha lógica implica que tudo seria uma palavra-chave. Há um pequeno conjunto de palavras-chave em uso em muitas linguagens de programação que podem ser detectadas e manipuladas de maneira útil em Java. O Java reservou gotoe constrefletiu sua herança C / C ++, mas eles não foram implementados (embora tenha havido debates sobre a implementação do último). Um casal mais gosta asserte enumnão foi inicialmente reservado, mas talvez devesse ter sido, uma vez que foram implementados. Mas retrospectiva é uma coisa maravilhosa.
dave
19

Eles são reservados para uso futuro (consulte: Palavras-chave da Linguagem Java )

As palavras-chave const e goto são reservadas, mesmo que não sejam usadas no momento.

A razão pela qual não há nenhuma instrução goto em Java pode ser encontrada em " The Java Language Environment ":

Java não tem instrução goto. Estudos ilustraram que o goto é (mis) usado com mais frequência do que não simplesmente "porque está lá". A eliminação do goto levou a uma simplificação do idioma - não há regras sobre os efeitos de um goto no meio de uma instrução for, por exemplo. Estudos em aproximadamente 100.000 linhas de código C determinaram que aproximadamente 90% das instruções goto foram usadas exclusivamente para obter o efeito de romper os loops aninhados. Como mencionado acima, a quebra em vários níveis e continua removendo a maior parte da necessidade de instruções goto.

Heinzi
fonte
gotoestá reservado, mas não para uso futuro.
Marquês de Lorne
17

Um exemplo de como usar rótulos "continue" em Java é:

public class Label {
    public static void main(String[] args) {
        int temp = 0;
        out: // label
        for (int i = 0; i < 3; ++i) {
            System.out.println("I am here");
            for (int j = 0; j < 20; ++j) {
                if(temp==0) {
                    System.out.println("j: " + j);
                    if (j == 1) {
                        temp = j;
                        continue out; // goto label "out"
                    }
                }
            }
        }
        System.out.println("temp = " + temp);
    }
}

Resultados:

I am here // i=0
j: 0
j: 1
I am here // i=1
I am here // i=2
temp = 1
andrew
fonte
10

É importante entender que a gotoconstrução é remanescente dos dias em que os programadores programaram em código de máquina e linguagem assembly. Como essas linguagens são tão básicas (como em, cada instrução faz apenas uma coisa), o fluxo de controle do programa é feito completamente com gotoinstruções (mas na linguagem assembly, elas são chamadas de instruções de salto ou ramificação ).

Agora, embora a linguagem C seja de nível bastante baixo, ela pode ser considerada uma linguagem assembly de nível muito alto - cada instrução e função em C pode ser facilmente dividida em instruções da linguagem assembly. Embora o C não seja o idioma principal para programar computadores atualmente, ele ainda é muito usado em aplicativos de baixo nível, como sistemas embarcados. Como a função C reflete tanto a função da linguagem assembly, faz sentido que isso gotoesteja incluído em C.

É claro que Java é uma evolução do C / C ++. Java compartilha muitos recursos do C, mas abstrai muito mais detalhes e, portanto, é simplesmente escrito de forma diferente. Java é uma linguagem de alto nível, portanto, simplesmente não é necessário ter recursos de baixo nível, como gotoquando construções de alto nível, como funções, para, para cada e enquanto loops, o fluxo de controle do programa. Imagine se você estivesse em uma função e fizesse gotoum rótulo em outra função. O que aconteceria quando a outra função retornasse? Essa ideia é absurda.

Isso não responde necessariamente por que o Java inclui a gotodeclaração e ainda não a deixa compilar, mas é importante saber por que gotofoi usado em primeiro lugar, em aplicativos de nível inferior, e por que simplesmente não faz sentido usado em Java.

Michael P na NCSU
fonte
"o fluxo de controle do programa é feito completamente com goto". Bem, nem sempre goto incondicional.
Peter Mortensen
Saltar com "goto" de uma função para um rótulo em outra função também não é possível em C / C ++. Saltar em C / C ++ é restrito a um único bloco de função.
user2328447
"simplesmente não é necessário ter recursos de baixo nível, como ir para construções de mais alto nível" - lembre-se de "Necessidade e suficiência". É apenas "não necessário". E, portanto, não há razão. O que é um motivo: "Ir para" como um substituto de "alto nível" para JMPs, BNEs e mais do Assembler é razoável se você quiser pular para o "código executável", mas o Java é um código de bytes e, portanto, não é "executável". ;-)
reichhart
10

Não, gotonão é usado, mas você pode definir rótulos e deixar um loop até o rótulo. Você pode usar breakou continueseguir o rótulo. Então você pode pular mais de um nível de loop. Dê uma olhada no tutorial .

Arne Burmeister
fonte
9

Não, felizmente, não existe gotoem Java.

A gotopalavra-chave é reservada apenas, mas não usada (o mesmo vale para const).

Bozho
fonte
Posso saber o que o reservado significa aqui? Se o uso de goto e const no código não é uma boa prática, por que eles o reservam? Você pode explicar, por favor?
Gopi
@ Sri Kumar: veja a resposta do @ applechewer, ela existe, mas não foi implementada.
Valentin Rocher
1
@ Sri Kumar: palavras-chave reservadas impedem que sejam usadas como nomes de variáveis ​​ou similares. Dessa maneira, essas palavras-chave podem ser implementadas em versões futuras do Java sem quebrar o código-fonte antigo que poderia ter sido usado de outra forma.
precisa
8

Porque não é suportado e por que você deseja uma gotopalavra - chave que não fez nada ou uma variável chamada goto?

Embora você possa usar break label;e continue label;instruções para efetivamente fazer o que gotofaz. Mas eu não recomendaria.

public static void main(String [] args) {

     boolean t = true;

     first: {
        second: {
           third: {
               System.out.println("Before the break");

               if (t) {
                  break second;
               }

               System.out.println("Not executed");
           }

           System.out.println("Not executed - end of second block");
        }

        System.out.println("End of third block");
     }
}
pjp
fonte
10
-1 Por que não devo ter uma variável ou método chamado goto?
22610 Michael Borgwardt
4
Porque tem um significado na área da programação que não é aplicável ao Java. Também é uma má escolha do nome da variável.
Pjp
Para que uma variável 'print' seria usada? As palavras que você mencionou são mais parecidas com nomes de métodos do que variáveis ​​ou palavras-chave.
PJP
3
-1: Antes de tudo, apenas porque o Java não suporta a instrução de controle de fluxo "goto", não significa que esse é o motivo pelo qual a palavra-chave "goto" não faz nada. Segundo, "goto" pode ser um nome de variável ruim, mas pode ser um excelente nome de método, que não podemos usar porque "goto" é uma palavra-chave. Terceiro, "etiqueta de interrupção" e "etiqueta de continuação" existem por um motivo muito bom; portanto, "não recomendar" não é muito útil. E quarto, como a Sun diz que "atualmente não é usada", provavelmente significa que eles planejaram implementar, mas não quiseram se livrar da palavra-chave quando decidiram o contrário.
Vojislav Stojkovic
2
@VojislavStojkovic Isso é apenas uma conversa maluca. 1) Que é por isso que ele não faz nada é porque ele não apoiá-lo. De acordo com o JLS, The keywords const and goto are reserved, even though they are not currently used. This may allow a Java compiler to produce better error messages if these C++ keywords incorrectly appear in programs.isso significa "Nós não o usamos, portanto, se você é oriundo de C ++, não vamos permitir que você o use". 2) gotoé um nome de método terrível. Desculpe. 3) quebrar e continuar são recomendados, mas não da maneira usada aqui . 4) "provavelmente" [citação necessária].
precisa saber é o seguinte
7

Não, gotonão é usado em Java, apesar de ser uma palavra reservada. O mesmo vale para const. Ambos são usados ​​em C ++, provavelmente o motivo pelo qual estão reservados; a intenção provavelmente era evitar confundir os programadores de C ++ migrando para Java e talvez também manter a opção de usá-los em revisões posteriores do Java.

Michael Borgwardt
fonte
1
Eu realmente espero que gotonão é suportado no futuro próximo, pelo menos;)
Bozho
6
@Bozho: bem, poderia ser usado para algum novo recurso engenhoso que não tem absolutamente nada a ver com o velho goto "prejudicial".
Michael Borgwardt
3

Observe que você pode substituir a maioria dos usos benignos de goto por

  • Retorna

  • pausa

  • etiqueta de quebra

  • jogue dentro try-catch-finalmente

starblue
fonte
5
Exceções NUNCA deve ser usado para controle de fluxo
ChssPly76
13
Exceções são usadas para controle de fluxo, mas devem ser usadas apenas para casos excepcionais. Por exemplo, um dos usos do goto em C é o tratamento de erros, especialmente se envolver limpeza.
Starblue
2
@ starblue, você tirou as palavras da minha boca. Lançar uma exceção é o fluxo de controle. Na verdade, em C, você pode implementar de maneira um pouco limpa o tratamento de exceções via setjmp / longjmp, certificando-se de definir primeiro o código de tratamento e executando longjmp () na exceção.
Eu quero fazer uma verificação se e pular a metade do método, se for verdade. Sem ir, devo usar outro gigante. IMO, é muito feio como muitos parêntese cria confusões
WVrock
1
@WVrock Você poderia tentarreturn
Andrew Lazarus
2

Como foi apontado, não existe gotono Java, mas a palavra-chave foi reservada caso a Sun sentisse vontade de adicionar gotoao Java um dia. Eles queriam poder adicioná-lo sem quebrar muito código, então reservaram a palavra-chave. Observe que no Java 5 eles adicionaram a enumpalavra-chave e ela também não quebrou tanto código.

Embora o Java não possua goto, ele tem algumas construções que correspondem a alguns usos de goto, ou seja, poder breake continuecom loops nomeados. Além disso, finallypode ser pensado como uma espécie de distorção goto.

Thomas Pornin
fonte
1

Proibir declarações de variáveis ​​com o mesmo nome.

por exemplo int i = 0, goto;

Karl
fonte
3
Mas porque ? Por que não devemos ter permissão para fazer essas declarações?
Aproximando-se
1

É muito considerada uma daquelas coisas que você não faz, mas provavelmente foi listada como uma palavra reservada para evitar confusão para os desenvolvedores.

Dean J
fonte
1

http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.goto

Se você foi informado de que não existe uma declaração goto em Java, você foi enganado. De fato, Java consiste em duas camadas de código 'fonte'.

Mikael Lindlöf
fonte
5
é como dizer que qualquer idioma tem que ir, porque existe uma ramificação incondicional no código do assembly por baixo de tudo. Ter o goto no código de bytes não significa que exista um goto em java porque "in java" significa "Na linguagem java", e o código de bytes não é uma camada de origem.
@ tgm1024, "em Java" também pode ser interpretado como "na plataforma Java". O compilador Java precisa produzir o bytecode Java ou a saída não funcionará na plataforma Java JVM. O C ++, por exemplo, não especifica a saída da compilação e o compilador é livre para produzir qualquer forma de código de máquina (ou qualquer outro código). O aplicativo programado Java bytecode pode ser chamado de "aplicativo Java", mas o aplicativo programado por código de máquina não pode ser chamado de "aplicativo C ++".
Mikael Lindlöf
2
Eu sei muito bem o que é java bytecode. Eu codifiquei pela primeira vez em java em 1996. E você pode ter outros idiomas para gerar bytecode em java para a JVM. Onde eu estou corrigindo você é a ideia de que existem duas camadas de fonte. Não há. Você possui fonte java e isso é compilado no código de java byte (executado pela JVM) e essa não é uma camada adicional de origem. Só porque existe um "goto" no código de bytes não significa que existe um "goto" em java. Java nomeou quebras e nomeou continua, mas não vai.
@ tgm1024 Fui acordado por um voto negativo :) Pode parecer facilmente que perdi a discussão desde que você fez o último comentário e suas credenciais são impressionantes. Meu argumento, que eu estava desenvolvendo, era que é muito possível programar com o bytecode Java. Para garantir a você, ainda há uma pergunta sobre isso: stackoverflow.com/questions/3150254/…
Mikael Lindlöf 5/16
1

Também não sou fã goto, pois geralmente torna o código menos legível. No entanto, acredito que há exceções a essa regra (especialmente quando se trata de lexers e analisadores!)

É claro que você sempre pode trazer seu programa para o Kleene Normalform traduzindo-o para algo semelhante a um montador e depois escrevendo algo como

int line = 1;
boolean running = true;
while(running)
{
    switch(line++)
    {
        case 1: /* line 1 */
                break;
        case 2: /* line 2 */
                break;
        ...
        case 42: line = 1337; // goto 1337
                break;
        ...
        default: running = false;
                break;
    }
}

(Então, basicamente, você escreve uma VM que executa seu código binário ... onde linecorresponde ao ponteiro da instrução)

Isso é muito mais legível do que o código que usa goto, não é?

Viktor Engelmann
fonte
Próxima pergunta: "Existe uma instrução switch em Python"
Mark K Cowan
0

Claro que é palavra-chave, mas não é usada no nível do código-fonte.

Mas se você usa jasmin ou outra linguagem de nível inferior, que é transformada em bytecode, então "goto" está lá

user1722245
fonte
-1

Porque, embora a linguagem Java não a use, o JVM bytecode o faz.

gribnit
fonte
7
Então, por que o idioma não possui uma loadpalavra - chave?
Aproximando-se
3
@gribnit, ter que ir ao bytecode por si só não significa nada para palavras reservadas de nível superior.