Esiste un'istruzione goto in Java?


259

Sono confuso su questo. Alla maggior parte di noi è stato detto che non ci sono dichiarazioni goto in Java.

Ma ho scoperto che è una delle parole chiave in Java. Dove può essere utilizzato? Se non può essere utilizzato, perché è stato incluso in Java come parola chiave?


13
solo un consiglio: non usare mai goto
lostiniceland il

16
E poi c'è "Vai all'istruzione considerato dannoso 'Considerato dannoso" e "" Vai all'istruzione considerato dannoso "Considerato dannoso' Considerato dannoso?" VEEEEERY ricorsivo, questo meme.
Chris Charabaruk,

70
'goto' è sempre male - come in 'goto work' o 'goto school';)
Andreas Dolk,

24
Il vero motivo è che la parola "g ** o" è considerata oscena nella maggior parte dei linguaggi di programmazione. I designer Java stanno solo proteggendo innocenti giovani programmatori da influenze corruttive. (:-))
Stephen C

25
La caccia alle streghe contro Goto ha generato alcuni dei momenti più aggravanti della mia vita. Ho visto persone contorcere il codice C nascondendo la funzionalità nelle funzioni, inserendo assurde logiche di uscita in loop multi-nidificati, e altrimenti facendo ogni forma di ingegneria eccessiva immaginabile SOLO per evitare che qualcuno critichi il loro codice in una revisione del codice. Questa regola, insieme alla canard "devi evitare ritorni multipli", è impregnata di sciocchezze. Ci sono momenti in cui goto rende le cose meno gestibili. Ci sono momenti in cui goto rende le cose più gestibili. Speravo così tanto che questa caccia alle streghe sarebbe morta negli anni '80.

Risposte:


200

L' elenco delle gotoparole chiave Java specifica la parola chiave, ma è contrassegnata come "non utilizzata".

Era nella JVM originale (vedi risposta di @VitaliiFedorenko ), ma poi rimosso. Probabilmente è stato mantenuto come parola chiave riservata nel caso in cui dovesse essere aggiunto a una versione successiva di Java.

Se gotonon fosse nell'elenco e verrà aggiunto successivamente alla lingua, il codice esistente che utilizzava la parola gotocome identificatore (nome della variabile, nome del metodo, ecc ...) si interromperebbe. Ma poiché gotoè una parola chiave, tale codice non verrà nemmeno compilato nel presente, e rimane possibile farlo effettivamente fare qualcosa in seguito, senza rompere il codice esistente.


29
This was probably done in case it were to be added to a later version of Java.In realtà, il motivo principale è un po 'diverso (vedi la mia risposta di seguito)
Vitalii Fedorenko,

2
Questa è un'informazione buona e interessante, ma non spiega perché è ancora una parola chiave riservata.
Thomas,

@Thomas Non hai descritto perché è riservato? È una parola chiave, quindi non può essere utilizzata ora; più tardi goto potrebbe prendere vita senza causare problemi. Se non fosse una parola riservata, ora potrebbe essere usata per produrre codice (int goto = 2;) che si spezzerebbe se fosse introdotto goto.

230

James Gosling ha creato la JVM originale con il supporto delle gotodichiarazioni, ma poi ha rimosso questa funzione come inutile. Il motivo principale non gotoè necessario che di solito può essere sostituito con istruzioni più leggibili (come break/continue) o estraendo un pezzo di codice in un metodo.

Fonte: James Gosling, sessione di domande e risposte


24
"... o estraendo un pezzo di codice in un metodo" - che deve essere molto bello senza un'adeguata eliminazione della coda.
Visualizza nome

45
A volte, un uso giudizioso di goto è il modo più pronto e chiaro per esprimere qualcosa, quindi forzarlo in qualcos'altro è necessariamente meno leggibile .
Deduplicatore,

1
@Deduplicator L'utilizzo di goto, per quanto giudizioso, è sempre soggetto a errori.
Çelebi Murat,

@Deduplicator L'unico uso di goto considerato buona pratica in C ++ è supportato da break / continue.
Inverno

2
Essere una parola chiave riservata in Java è fantastico perché impedisce alle persone di nominare le etichette "goto:".
Inverno

147

La parola chiave esiste, ma non è implementata.

L'unico buon motivo per usare goto che mi viene in mente è questo:

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:

In Java puoi farlo in questo modo:

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: reindirizza il codice sull'etichetta, proprio prima del primo ciclo.
assylias,

21
@assylias Beh, non proprio. L'etichetta identifica il circuito esterno. Quindi break loopssignifica "uscire dal loop chiamato loops". Forse a posteriori potrebbe essere stato un nome migliore per l'etichetta outer.
jonnystoten,

8
"L'unico buon motivo per usare goto" I piccoli programmi veloci e sporchi che richiedono un ciclo infinito incondizionato fanno un grande uso di goto. L'uso di while (true) {... }è eccessivo. GOTO è spesso stigmatizzato per i suoi usi impropri, ma sostengo che confronti inutili con letterali booleani è peggio di GOTO.
Alexander - Ripristina Monica il

1
L'etichetta dei loop non dovrebbe essere dopo i loop?
GC_

1
Di recente ho scoperto che questa tecnica di etichettatura è anche molto utile in combinazione con continue LABEL;un'affermazione. Quindi puoi continuare un anello disteso esterno.
infotoni91,


29

Quindi potrebbero essere usati un giorno se i progettisti del linguaggio ne sentissero il bisogno.

Inoltre, se i programmatori di lingue che dispongono di queste parole chiave (ad es. C, C ++) le usano per errore, il compilatore Java può fornire un utile messaggio di errore.

O forse era solo per fermare i programmatori che usano goto :)


La funzionalità goto mancante in Java dovrebbe essere una ragione sufficiente per non usare goto: non è necessario prenotarla come parola chiave. Seguendo la tua logica, tutto sarebbe una parola chiave, dal momento che è usato da altre lingue e / o dai progettisti Java POTREBBE usarlo in futuro ...
stuXnet

1
Non penso che la mia logica implichi che tutto sarebbe una parola chiave. C'è un piccolo insieme di parole chiave in uso in molti linguaggi di programmazione che possono essere utilmente rilevate e gestite in Java. Java ha riservato gotoe constrispecchiato la sua eredità C / C ++ ma rimane non implementato (anche se ci sono stati dibattiti sull'attuazione di quest'ultimo). Un altro paio piace asserte enuminizialmente non erano riservati, ma forse avrebbero dovuto esserlo, dato che sono stati implementati. Ma il senno di poi è una cosa meravigliosa.
Dave,

19

Sono riservati per uso futuro (consultare: Parole chiave in linguaggio Java )

Le parole chiave const e goto sono riservate, anche se non sono attualmente utilizzate.

Il motivo per cui non esiste alcuna istruzione goto in Java si trova in " Java Language Environment ":

Java non ha alcuna dichiarazione goto. Gli studi hanno dimostrato che il goto è (mis) usato più spesso del semplice "perché è lì". L'eliminazione del goto ha portato a una semplificazione del linguaggio - non ci sono regole sugli effetti di un goto nel mezzo di un'istruzione for, ad esempio. Gli studi su circa 100.000 righe di codice C hanno determinato che circa il 90 percento delle dichiarazioni goto sono state utilizzate puramente per ottenere l'effetto della rottura di cicli annidati. Come accennato in precedenza, l'interruzione multilivello e continua rimuovono la maggior parte della necessità di dichiarazioni goto.


gotoè riservato, ma non per uso futuro.
Marchese di Lorne,

17

Un esempio di come utilizzare le etichette "continue" in 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);
    }
}

risultati:

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

10

È importante capire che il gotocostrutto è rimasto dai giorni programmati dai programmatori nel codice macchina e nel linguaggio assembly. Poiché tali lingue sono così basilari (come in, ogni istruzione fa solo una cosa), il flusso di controllo del programma viene eseguito completamente con le gotoistruzioni (ma nel linguaggio assembly, queste vengono chiamate istruzioni jump o branch ).

Ora, sebbene il linguaggio C sia piuttosto di basso livello, può essere pensato come un linguaggio assembly di alto livello - ogni istruzione e funzione in C può essere facilmente suddivisa in istruzioni del linguaggio assembly. Sebbene C non sia il linguaggio principale con cui programmare i computer al giorno d'oggi, è ancora ampiamente utilizzato in applicazioni di basso livello, come i sistemi embedded. Poiché la funzione di C rispecchia così da vicino la funzione del linguaggio assembly, ha senso solo che gotosia inclusa in C.

È chiaro che Java è un'evoluzione di C / C ++. Java condivide molte funzionalità di C, ma estrae molti più dettagli e quindi è semplicemente scritto in modo diverso. Java è un linguaggio di alto livello, quindi semplicemente non è necessario disporre di funzionalità di basso livello come gotoquando più costrutti di alto livello come funzioni, per, per ciascuno, e mentre i loop eseguono il flusso di controllo del programma. Immagina se fossi in una funzione e facessi gotoa un'etichetta in un'altra funzione. Cosa succederebbe quando l'altra funzione tornasse? Questa idea è assurda.

Questo non risponde necessariamente al motivo per cui Java includa l' gotoistruzione ma non la lascerà compilare, ma è importante sapere perché gotoè mai stato usato in primo luogo, nelle applicazioni di livello inferiore e perché non ha senso essere utilizzato in Java.


"Il flusso di controllo del programma viene eseguito completamente con goto". Bene, non sempre andare incondizionato.
Peter Mortensen,

Saltare con "goto" da una funzione a un'etichetta in un'altra funzione non è anche possibile in C / C ++. Andare in C / C ++ è limitato a un singolo blocco funzione.
user2328447

"semplicemente non è necessario avere caratteristiche di basso livello come goto quando più costrutti di alto livello" - ricorda "Necessità e sufficienza". È semplicemente "non necessario". E quindi nessuna ragione. Che cos'è un motivo: "Vai a" come sostituto "di alto livello" di JMP, BNE e altri assemblatori è ragionevole se vuoi passare al "codice eseguibile" ma Java è bytecode e quindi non "eseguibile". ;-)
Reichhart,

10

No, gotonon viene utilizzato, ma è possibile definire etichette e lasciare un ciclo fino all'etichetta. Puoi usare breako continueseguire l'etichetta. Quindi puoi saltare più di un livello di loop. Dai un'occhiata al tutorial .


9

No, per fortuna, non c'è gotoin Java.

La gotoparola chiave è solo riservata, ma non utilizzata (lo stesso vale per const).


Posso sapere cosa significava il riservato qui? Se usare il codice goto e const in non è una buona pratica, perché lo riservano? Puoi spiegare per favore?
Gopi,

@Sri Kumar: vedi la risposta di @appechewer, esiste ma non è implementata.
Valentin Rocher,

1
@Sri Kumar: le parole chiave riservate ne impediscono l'utilizzo come nomi di variabili o simili. In questo modo, queste parole chiave possono essere implementate nelle future versioni di Java senza rompere il vecchio codice sorgente che altrimenti avrebbe potuto usarle.
Peter Di Cecco

8

Perché non è supportato e perché dovresti desiderare una gotoparola chiave che non ha fatto nulla o una variabile denominata goto?

Sebbene sia possibile utilizzare break label;e le continue label;istruzioni per fare effettivamente ciò che gotofa. Ma non lo consiglierei.

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 Perché non dovrei avere la possibilità di avere una variabile o un metodo chiamato goto?
Michael Borgwardt,

4
Perché ha un significato nel campo della programmazione che non è applicabile a Java. È anche una cattiva scelta del nome della variabile.
pjp,

Per che cosa verrebbe utilizzata una variabile 'print'? Le parole che hai citato sono più simili a nomi di metodi che a variabili o parole chiave.
pjp,

3
-1: Prima di tutto, solo perché Java non supporta l'istruzione di controllo del flusso "goto", non significa che sia la ragione per cui ha la parola chiave "goto" che non fa nulla. In secondo luogo, "goto" potrebbe essere un nome di variabile scadente, ma può essere un nome di metodo eccellente, che non possiamo usare perché "goto" è una parola chiave. In terzo luogo, "break label" e "continue label" esistono per un'ottima ragione, quindi "non raccomandarlo" non è molto utile. In quarto luogo, poiché Sun afferma che "non è attualmente utilizzato", molto probabilmente significa che una volta avevano pianificato l'implementazione, ma non volevano sbarazzarsi della parola chiave quando hanno deciso diversamente.
Vojislav Stojkovic,

2
@VojislavStojkovic È solo un discorso folle. 1) Questo è il motivo per cui non si fa nulla è perché non lo supporta. Secondo 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.Questo significa "Non lo usiamo, quindi se provieni da uno sfondo C ++ non ti lasceremo affatto." 2) gotoè un nome di metodo terribile. Scusate. 3) si consiglia di interrompere e continuare, ma non nel modo utilizzato qui . 4) "molto probabilmente" [citazione necessaria].
corsiKa

7

No, gotonon viene utilizzato in Java, nonostante sia una parola riservata. Lo stesso vale per const. Entrambi sono usati in C ++, che è probabilmente il motivo per cui sono riservati; l'intenzione era probabilmente quella di evitare di confondere i programmatori C ++ che migravano verso Java e forse anche di mantenere la possibilità di usarli nelle successive revisioni di Java.


1
Spero davvero che gotonon sia supportato almeno nel prossimo futuro;)
Bozho,

6
@Bozho: beh, potrebbe essere usato per alcune nuove ingegnose funzionalità che non hanno assolutamente nulla a che fare con il vecchio cattivo "dannoso" goto.
Michael Borgwardt,

3

Nota che puoi sostituire la maggior parte degli usi benigni di goto con

  • ritorno

  • rompere

  • etichetta di rottura

  • gettare dentro try-catch-finalmente


5
Le eccezioni non devono MAI essere utilizzate per il controllo del flusso
ChssPly76,

13
Le eccezioni vengono utilizzate per il controllo del flusso, ma dovrebbero essere utilizzate solo in casi eccezionali. Ad esempio, uno degli usi di goto in C è la gestione degli errori, soprattutto se comporta la pulizia.
Starblue,

2
@starblue, mi hai tolto le parole dalla bocca. Generare un'eccezione è il flusso di controllo. In C, infatti, puoi implementare in qualche modo in modo chiaro la gestione delle eccezioni tramite setjmp / longjmp assicurandoti di impostare prima jjmp sul codice di gestione ed eseguendo longjmp () ing su di esso su eccezione.

Voglio fare un controllo if e saltare la metà del metodo se vero. Senza andare a devo usare un altro gigante. IMO è abbastanza brutto perché troppe parantesi creano confusione
WVrock,

1
@WVrock Potresti provarereturn
Andrew Lazarus,

2

Come è stato sottolineato, non esiste gotoin Java, ma la parola chiave è stata riservata nel caso in cui Sun avesse voglia di aggiungere gotoa Java un giorno. Volevano essere in grado di aggiungerlo senza rompere troppo codice, quindi hanno prenotato la parola chiave. Si noti che con Java 5 hanno aggiunto la enumparola chiave e neanche quel codice ha infranto molto.

Sebbene Java non abbia goto, ha alcuni costrutti che corrispondono ad alcuni usi di goto, vale a dire essere in grado di breake continuecon loop denominati. Inoltre, finallypuò essere pensato come una sorta di contorto goto.


1

Proibire dichiarazioni di variabili con lo stesso nome.

per esempio int i = 0, goto;


3
Ma perchè ? Perché non dovremmo essere autorizzati a fare queste dichiarazioni?
ApproachingDarknessFish

1

È considerata una di quelle cose che non devi fare, ma probabilmente è stata elencata come una parola riservata per evitare confusione per gli sviluppatori.


1

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

Se ti è stato detto che non ci sono dichiarazioni goto in Java, sei stato ingannato. In effetti, Java è costituito da due livelli di codice "sorgente".


5
è come dire che qualsiasi linguaggio ha un goto perché esiste un ramo incondizionato nel codice assembly sotto tutto. Avere il goto nel codice byte non significa che ci sia un goto in java perché "in java" significa "nel linguaggio java", e il codice byte non è un livello di origine.

@ tgm1024, "in Java" può anche essere interpretato come "in piattaforma Java". Il compilatore Java deve produrre il bytecode Java o l'output non funzionerà nella piattaforma Java JVM. C ++, ad esempio, non specifica l'output della compilazione e il compilatore è libero di produrre qualsiasi forma di codice macchina (o qualsiasi altro codice). L'applicazione programmata bytecode Java può essere chiamata "applicazione Java" ma l'applicazione programmata con codice macchina non può essere chiamata "applicazione C ++".
Mikael Lindlöf,

2
So benissimo cos'è il bytecode java. Ho programmato per la prima volta Java nel 1996. E puoi avere altre lingue per generare il codice java Java per la JVM. Dove ti sto correggendo è questa idea che ci sono due livelli di fonte. Non ci sono. Hai java source e questo è compilato in java byte code (eseguito da JVM) e questo non è un ulteriore livello di source. Solo perché c'è un "goto" nel codice byte non significa che c'è un "goto" in java. Java ha chiamato le interruzioni e il nome continua, ma non va.

@ tgm1024 Sono stato svegliato da un downvote :) Può facilmente sembrare che ho perso l'argomento da quando hai fatto l'ultimo commento e le tue credenziali sono impressionanti. Il mio punto, che stavo costruendo, era che è molto possibile programmare con bytecode Java. Per assicurare, ecco anche un dubbio su questo: stackoverflow.com/questions/3150254/...
Mikael Lindlöf


1

Nemmeno io sono un fan goto, poiché di solito rende il codice meno leggibile. Comunque credo che ci siano eccezioni a quella regola (specialmente quando si tratta di lexer e parser!)

Ovviamente puoi sempre portare il tuo programma in Kleene Normalform traducendolo in qualcosa di simile ad un assemblatore e poi scrivendo qualcosa di simile

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

(Quindi in pratica scrivi una VM che esegue il tuo codice binario ... dove linecorrisponde al puntatore dell'istruzione)

È molto più leggibile del codice che usa goto, no?


Domanda successiva, "Esiste un'istruzione switch in Python"
Mark K Cowan,

0

Naturalmente è una parola chiave, ma non viene utilizzata a livello di codice sorgente.

Ma se usi jasmin o un altro linguaggio di livello inferiore, che viene trasformato in bytecode, allora "goto" è lì


-1

Perché sebbene il linguaggio Java non lo usi, il bytecode JVM lo fa.


7
Allora perché la lingua non ha una loadparola chiave?
Approaching

3
@gribnit, avere un goto in bytecode non significa da solo nulla per le parole riservate di livello superiore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.