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?


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.


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


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

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


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 :)


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.


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

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.


"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 .


9

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

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


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");
     }
}

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.


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


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.


1

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

por exemplo int i = 0, goto;


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.


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'.


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 é?


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á


-1

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


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.