Gibt es eine goto-Anweisung in Java?

259

Ich bin verwirrt darüber. Den meisten von uns wurde gesagt, dass es in Java keine goto-Anweisung gibt.

Aber ich fand, dass es eines der Schlüsselwörter in Java ist. Wo kann es verwendet werden? Wenn es nicht verwendet werden kann, warum wurde es dann in Java als Schlüsselwort aufgenommen?

Venkat
quelle
13
Nur ein Ratschlag: Verwenden Sie niemals goto
lostiniceland
16
Und dann gibt es "Gehe zu Aussage, die als schädlich angesehen wird" und "Gehe zu Aussage, die als schädlich angesehen wird", die als schädlich angesehen wird. VEEEEERY rekursiv, dieses Mem.
Chris Charabaruk
70
'goto' ist immer böse - wie in 'goto work' oder 'goto school';)
Andreas Dolk
24
Der wahre Grund ist, dass das Wort "g ** o" in den meisten Programmiersprachen als obszön angesehen wird. Die Java-Designer schützen nur unschuldige junge Programmierer vor korrumpierenden Einflüssen. (:-))
Stephen C
25
Die Hexenjagd gegen goto hat einige der schlimmsten Momente in meinem Leben hervorgebracht. Ich habe gesehen, wie Leute C-Code verfälschten, indem sie Funktionen in Funktionen versteckten, absurde Exit-Logik in mehrfach verschachtelte Schleifen steckten und ansonsten jede erdenkliche Form von Überentwicklung NUR durchführten, um zu vermeiden, dass jemand ihren Code in einer Codeüberprüfung kritisierte. Diese Regel ist zusammen mit dem Canard "Du musst mehrfache Rückgaben vermeiden" voller Unsinn. Es gibt Zeiten, in denen goto die Dinge weniger wartbar macht. Es gibt Zeiten, in denen goto die Dinge wartbarer macht. Ich hatte so gehofft, dass diese Hexenjagd in den 80ern gestorben wäre.

Antworten:

200

Die Java-Schlüsselwortliste gibt das gotoSchlüsselwort an, wird jedoch als "nicht verwendet" markiert.

Es war in der ursprünglichen JVM (siehe Antwort von @VitaliiFedorenko ), wurde dann aber entfernt. Es wurde wahrscheinlich als reserviertes Schlüsselwort beibehalten, falls es einer späteren Version von Java hinzugefügt werden sollte.

Wenn dies gotonicht in der Liste enthalten ist und später zur Sprache hinzugefügt wird, wird der vorhandene Code, der das Wort gotoals Bezeichner verwendet (Variablenname, Methodenname usw.), beschädigt. Da es sich jedoch gotoum ein Schlüsselwort handelt, wird ein solcher Code in der Gegenwart nicht einmal kompiliert, und es bleibt möglich, ihn später tatsächlich dazu zu bringen, etwas zu tun, ohne vorhandenen Code zu beschädigen.

Thomas
quelle
29
This was probably done in case it were to be added to a later version of Java.Eigentlich ist der Hauptgrund ein bisschen anders (siehe meine Antwort unten)
Vitalii Fedorenko
2
Das sind gute und interessante Informationen, aber es erklärt nicht, warum es immer noch ein reserviertes Schlüsselwort ist.
Thomas
@ Thomas Hast du nicht beschrieben, warum es reserviert ist? Es ist ein Schlüsselwort, daher kann es jetzt nicht verwendet werden. später konnte goto zum Leben erwecken, ohne Probleme zu verursachen. Wenn es kein reserviertes Wort wäre, könnte es jetzt verwendet werden, um Code (int goto = 2;) zu erzeugen, der bei Einführung von goto brechen würde.
230

James Gosling erstellte die ursprüngliche JVM mit Unterstützung von gotoAussagen, entfernte diese Funktion jedoch als unnötig. Der Hauptgrund gotoist unnötig, dass es normalerweise durch besser lesbare Anweisungen (wie break/continue) oder durch Extrahieren eines Codeteils in eine Methode ersetzt werden kann.

Quelle: James Gosling, Q & A-Sitzung

Vitalii Fedorenko
quelle
24
"... oder durch Extrahieren eines Codeteils in eine Methode" - das muss sehr cool sein, ohne dass der Tail Call ordnungsgemäß beseitigt wird.
Anzeigename
45
Manchmal ist eine vernünftige Nutzung goto ist die readyble und klare Art und Weise etwas zum Ausdruck bringen, so es sonst zu nichts zwingt , ist notgedrungen weniger lesbar .
Deduplikator
1
@Deduplicator Die Verwendung von goto, so vernünftig es auch sein mag, ist immer fehleranfällig.
Çelebi Murat
@Deduplicator Die einzige Verwendung von goto, die in C ++ als gute Übung angesehen wird, wird durch break / continue unterstützt.
Winter
2
Es ist großartig, ein reserviertes Schlüsselwort in Java zu sein, da es verhindert, dass Benutzer Labels "goto:" nennen.
Winter
147

Das Schlüsselwort ist vorhanden, wird jedoch nicht implementiert.

Der einzige gute Grund, goto zu verwenden, den ich mir vorstellen kann, ist folgender:

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 können Sie dies folgendermaßen tun:

loops:
for (int i = 0; i < MAX_I; i++) {
    for (int j = 0; j < MAX_J; j++) {
        // do stuff
        break loops;
    }
}
jonnystoten
quelle
1
@ Zoltán Nein - der Code wird direkt vor der ersten Schleife auf das Etikett umgeleitet.
Assylias
21
@assylias Nun, nicht ganz. Das Etikett kennzeichnet die äußere Schleife. Dann break loopsbedeutet "Ausbruch aus der aufgerufenen Schleife loops". Vielleicht wäre im Nachhinein ein besserer Name für das Label gewesen outer.
Jonnystoten
8
"Der einzig gute Grund, goto zu verwenden" Schnelle und schmutzige kleine Programme, die eine bedingungslose Endlosschleife benötigen, nutzen goto sehr gut. Verwenden von while (true) {... }ist übertrieben. GOTO wird häufig wegen seiner missbräuchlichen Verwendung stigmatisiert, aber ich behaupte, dass unnötige Vergleiche mit booleschen Literalen schlechter sind als GOTO.
Alexander - Reinstate Monica
1
Sollte das Loops-Label nicht hinter den Loops stehen?
GC_
1
Ich habe kürzlich entdeckt, dass diese Kennzeichnungstechnik auch in Kombination mit einer continue LABEL;Aussage sehr nützlich ist . So können Sie eine äußere liegende Schleife fortsetzen.
infotoni91
43

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

"Die Schlüsselwörter const und goto sind reserviert, obwohl sie derzeit nicht verwendet werden."

Isaac E.
quelle
12
"unsigned" ist nicht mal da! (Seufzer)
Matthieu
Sinnvoll, da alle primitiven Typen in Java signiert sind.
Mwieczorek
1
@mwieczorek Nicht alle. "char" ist ein primitiver Typ und ohne Vorzeichen.
Sergey Krivenkov
29

Sie könnten also eines Tages verwendet werden, wenn die Sprachdesigner das Bedürfnis verspüren.

Wenn Programmierer aus Sprachen, die diese Schlüsselwörter haben (z. B. C, C ++), diese versehentlich verwenden, kann der Java-Compiler eine nützliche Fehlermeldung ausgeben.

Oder vielleicht war es nur, um Programmierer davon abzuhalten, goto zu verwenden :)

Dave
quelle
Die fehlende goto-Funktionalität in Java sollte Grund genug sein, goto nicht zu verwenden - es ist nicht erforderlich, sie als Schlüsselwort zu reservieren. Nach Ihrer Logik wäre alles ein Schlüsselwort, da es entweder von anderen Sprachen verwendet wird und / oder die Java-Designer es in Zukunft verwenden
KÖNNTEN
1
Ich glaube nicht, dass meine Logik impliziert, dass alles ein Schlüsselwort wäre. In vielen Programmiersprachen wird eine kleine Anzahl von Schlüsselwörtern verwendet, die in Java sinnvoll erkannt und verarbeitet werden können. Java reserviert gotound constspiegelt sein C / C ++ - Erbe wider, aber sie bleiben nicht implementiert (obwohl es Debatten über die Implementierung des letzteren gab). Ein paar mehr wie assertund enumwaren anfangs nicht reserviert, sollten es aber vielleicht gewesen sein, da sie implementiert wurden. Aber im Nachhinein ist eine wunderbare Sache.
Dave
19

Sie sind für die zukünftige Verwendung reserviert (siehe: Java Language Keywords )

Die Schlüsselwörter const und goto sind reserviert, obwohl sie derzeit nicht verwendet werden.

Der Grund, warum es in Java keine goto-Anweisung gibt, finden Sie in " The Java Language Environment ":

Java hat keine goto-Anweisung. Studien haben gezeigt, dass goto (falsch) häufig verwendet wird, nicht nur "weil es da ist". Das Eliminieren von goto führte zu einer Vereinfachung der Sprache - es gibt beispielsweise keine Regeln für die Auswirkungen eines goto in die Mitte einer for-Anweisung. Studien mit ungefähr 100.000 Zeilen C-Code ergaben, dass ungefähr 90 Prozent der goto-Anweisungen nur verwendet wurden, um den Effekt des Ausbrechens verschachtelter Schleifen zu erzielen. Wie oben erwähnt, wird durch mehrstufiges Unterbrechen und Fortfahren der größte Teil der Notwendigkeit von goto-Anweisungen beseitigt.

Heinzi
quelle
gotoist reserviert, aber nicht für zukünftige Verwendung.
Marquis von Lorne
17

Ein Beispiel für die Verwendung von "continue" -Labels in Java ist:

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

Ergebnisse:

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

Es ist wichtig zu verstehen, dass das gotoKonstrukt aus den Tagen stammt, als Programmierer in Maschinencode und Assemblersprache programmierten. Da diese Sprachen so einfach sind (wie in, jeder Befehl macht nur eine Sache), erfolgt der Programmsteuerungsfluss vollständig mit gotoAnweisungen (in der Assemblersprache werden diese jedoch als Sprung oder Verzweigung bezeichnet ).

Obwohl die C-Sprache relativ niedrig ist, kann sie als Assemblersprache auf sehr hoher Ebene betrachtet werden. Jede Anweisung und Funktion in C kann leicht in Assembler-Anweisungen unterteilt werden. Obwohl C heutzutage nicht die Hauptsprache zum Programmieren von Computern ist, wird es in Anwendungen auf niedriger Ebene wie eingebetteten Systemen immer noch häufig verwendet. Da die Funktion von C die Funktion der Assemblersprache so stark widerspiegelt, ist es nur sinnvoll, dass gotosie in C enthalten ist.

Es ist klar, dass Java eine Weiterentwicklung von C / C ++ ist. Java hat viele Funktionen von C gemeinsam, abstrahiert jedoch viel mehr Details und ist daher einfach anders geschrieben. Java ist eine Sprache auf sehr hoher Ebene, daher ist es einfach nicht erforderlich, Funktionen auf niedriger Ebene zu haben, wie gotowenn Konstrukte auf höherer Ebene wie Funktionen für jede und während Schleifen den Programmsteuerungsfluss ausführen. Stellen Sie sich vor, Sie wären in einer Funktion und hätten gotoeine Beschriftung in eine andere Funktion übernommen. Was würde passieren, wenn die andere Funktion zurückgegeben würde? Diese Idee ist absurd.

Dies beantwortet nicht unbedingt, warum Java die gotoAnweisung enthält , sie jedoch nicht kompilieren lässt, aber es ist wichtig zu wissen, warum sie gotoüberhaupt in Anwendungen auf niedrigerer Ebene verwendet wurde und warum es einfach keinen Sinn macht, sie zu verwenden in Java verwendet.

Michael P an der NCSU
quelle
"Der Programmablauf erfolgt vollständig mit goto". Nun, nicht immer bedingungslos.
Peter Mortensen
Das Springen mit "goto" von einer Funktion in ein Label in einer anderen Funktion ist in C / C ++ ebenfalls nicht möglich. Das Springen in C / C ++ ist auf einen einzelnen Funktionsblock beschränkt.
user2328447
"Es ist einfach nicht notwendig, Funktionen auf niedriger Ebene wie goto zu haben, wenn Konstrukte auf höherer Ebene erstellt werden" - denken Sie an "Notwendigkeit und Suffizienz". Es ist einfach "nicht notwendig". Und damit kein Grund. Was ist ein Grund: "Goto" als "High Level" -Ersatz für Assemblers JMPs, BNEs und mehr ist sinnvoll, wenn Sie zu "ausführbarem Code" springen möchten, Java jedoch Bytecode und daher nicht "ausführbar" ist. ;-)
Reichhart
10

Nein, gotowird nicht verwendet, aber Sie können Beschriftungen definieren und eine Schleife bis zur Beschriftung hinterlassen. Sie können das Etikett verwenden breakoder continuefolgen. Sie können also mehr als eine Loop-Ebene herausspringen. Schauen Sie sich das Tutorial an .

Arne Burmeister
quelle
9

Nein, zum Glück gibt es nicht gotoin Java.

Das gotoSchlüsselwort ist nur reserviert, wird aber nicht verwendet (dasselbe gilt für const).

Bozho
quelle
Darf ich wissen, was das Reservierte hier bedeutete? Wenn die Verwendung von goto und const im Code keine gute Vorgehensweise ist, warum reservieren sie diese? Kannst du bitte Erklären?
Gopi
@Sri Kumar: siehe @ applechewers Antwort, es existiert, aber es ist nicht implementiert.
Valentin Rocher
1
@Sri Kumar: Reservierte Schlüsselwörter verhindern, dass sie als Variablennamen oder ähnliches verwendet werden. Auf diese Weise können diese Schlüsselwörter in zukünftigen Java-Versionen implementiert werden, ohne dass der alte Quellcode beschädigt wird, der sie sonst hätte verwenden können.
Peter Di Cecco
8

Weil es nicht unterstützt wird und warum möchten Sie ein gotoSchlüsselwort, das nichts getan hat, oder eine Variable mit dem Namen goto?

Obwohl Sie break label;und continue label;Anweisungen verwenden können, um effektiv zu tun, was gototut. Aber ich würde es nicht empfehlen.

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
quelle
10
-1 Warum sollte ich keine Variable oder Methode namens goto haben dürfen?
Michael Borgwardt
4
Weil es im Land der Programmierung eine Bedeutung hat, die für Java nicht anwendbar ist. Es ist auch eine schlechte Wahl des Variablennamens.
pjp
Wofür würde eine Variable 'print' verwendet? Die Wörter, die Sie erwähnt haben, ähneln eher Methodennamen als Variablen oder Schlüsselwörtern.
pjp
3
-1: Nur weil Java die Flusskontrollanweisung "goto" nicht unterstützt, heißt das nicht, dass es das Schlüsselwort "goto" gibt, das nichts bewirkt. Zweitens ist "goto" möglicherweise ein schlechter Variablenname, aber es kann ein ausgezeichneter Methodenname sein, den wir nicht verwenden können, da "goto" ein Schlüsselwort ist. Drittens gibt es "Label brechen" und "Label fortsetzen" aus einem sehr guten Grund, so dass "es nicht empfehlen" nicht sehr nützlich ist. Und viertens, da Sun sagt, dass es "derzeit nicht verwendet" wird, bedeutet dies höchstwahrscheinlich, dass sie einmal geplant hatten, es zu implementieren, aber das Schlüsselwort nicht loswerden wollten, als sie sich anders entschieden.
Vojislav Stojkovic
2
@VojislavStojkovic Das ist nur verrücktes Gerede. 1) Das ist , warum es nichts tut , ist , weil sie es nicht unterstützt. Laut 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.bedeutet dies "Wir verwenden es nicht. Wenn Sie also aus einem C ++ - Hintergrund stammen, lassen wir Sie es überhaupt nicht verwenden." 2) gotoist ein schrecklicher Methodenname. Es tut uns leid. 3) Pause und Fortsetzung werden empfohlen, jedoch nicht in der hier verwendeten Weise . 4) "höchstwahrscheinlich" [Zitieren erforderlich].
CorsiKa
7

Nein, gotowird in Java nicht verwendet, obwohl es sich um ein reserviertes Wort handelt. Gleiches gilt für const. Beide werden in C ++ verwendet, was wahrscheinlich der Grund ist, warum sie reserviert sind. Die Absicht war wahrscheinlich, zu vermeiden, dass C ++ - Programmierer, die auf Java migrieren, verwirrt werden, und möglicherweise auch die Option beizubehalten, sie in späteren Versionen von Java zu verwenden.

Michael Borgwardt
quelle
1
Ich hoffe wirklich, dass gotoes in naher Zukunft nicht unterstützt wird;)
Bozho
6
@Bozho: Nun, es könnte für eine geniale neue Funktion verwendet werden, die absolut nichts mit dem schlechten alten "schädlichen" Goto zu tun hat.
Michael Borgwardt
3

Beachten Sie, dass Sie die meisten harmlosen Verwendungen von goto durch ersetzen können

  • Rückkehr

  • brechen

  • Etikett brechen

  • Wirf hinein, versuche es endlich

Sternenblau
quelle
5
Ausnahmen sollten
NIEMALS
13
Ausnahmen werden für die Flusskontrolle verwendet, sollten jedoch nur in Ausnahmefällen verwendet werden. Eine der Anwendungen von goto in C ist beispielsweise die Fehlerbehandlung, insbesondere wenn es sich um eine Bereinigung handelt.
Starblue
2
@starblue, du hast mir die Worte aus dem Mund genommen. Das Auslösen einer Ausnahme ist der Kontrollfluss. In C können Sie die Ausnahmebehandlung über setjmp / longjmp etwas sauber implementieren, indem Sie sicherstellen, dass Sie zuerst den Behandlungscode auf setjmp setzen und longjmp () für ihn in Ausnahmefällen ausführen.
Ich möchte eine if-Prüfung durchführen und die Hälfte der Methode überspringen, wenn dies der Fall ist. Ohne zu gehen muss ich einen anderen Riesen benutzen. IMO ist es ziemlich hässlich, da zu viele Klammern Verwirrung
stiften
1
@ WVrock Sie könnten versuchenreturn
Andrew Lazarus
2

Wie bereits erwähnt, gibt es gotoin Java kein Schlüsselwort, aber das Schlüsselwort wurde für den Fall reserviert, dass Sun gotoeines Tages Java hinzufügen möchte . Sie wollten es hinzufügen können, ohne zu viel Code zu beschädigen, deshalb haben sie das Schlüsselwort reserviert. Beachten Sie, dass sie mit Java 5 das enumSchlüsselwort hinzugefügt haben und es auch nicht so viel Code gebrochen hat.

Obwohl Java keine hat goto, hat es einige Konstrukte, die einigen Verwendungen von entsprechen goto, nämlich in der Lage zu sein breakund continuemit benannten Schleifen. Auch finallykann als eine Art verdreht gedacht goto.

Thomas Pornin
quelle
1

Deklaration von gleichnamigen Variablen verbieten.

z.B int i = 0, goto;

Karl
quelle
3
Aber warum ? Warum sollten wir diese Erklärungen nicht abgeben dürfen?
Annäherung an
1

Es wird sehr oft als eines der Dinge angesehen, die Sie nicht tun, wurde aber wahrscheinlich als reserviertes Wort aufgeführt, um Verwirrung für Entwickler zu vermeiden.

Dean J.
quelle
1

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

Wenn Ihnen gesagt wurde, dass es in Java keine goto-Anweisung gibt, wurden Sie getäuscht. In der Tat besteht Java aus zwei Schichten von 'Quellcode'.

Mikael Lindlöf
quelle
5
Das ist so, als würde man sagen, dass jede Sprache ein Goto hat, weil es im Assembler-Code darunter einen bedingungslosen Zweig gibt. Das Goto im Bytecode zu haben bedeutet nicht, dass es in Java ein Goto gibt, da "in Java" "In der Java-Sprache" bedeutet und Bytecode keine Quellebene ist.
@ tgm1024, "in Java" kann auch als "in Java-Plattform" interpretiert werden. Der Java-Compiler muss Java-Bytecode erzeugen, sonst funktioniert die Ausgabe in der Java-Plattform JVM nicht. In C ++ wird beispielsweise keine Kompilierungsausgabe angegeben, und der Compiler kann jede Art von Maschinencode (oder anderen Code) erstellen. Eine mit Java-Bytecode programmierte Anwendung kann als "Java-Anwendung" bezeichnet werden, eine mit Maschinencode programmierte Anwendung kann jedoch nicht als "C ++ - Anwendung" bezeichnet werden.
Mikael Lindlöf
2
Ich weiß genau, was Java-Bytecode ist. Ich habe 1996 zum ersten Mal in Java codiert. Und Sie können andere Sprachen Java-Bytecode für die JVM generieren lassen. Wo ich Sie korrigiere, ist die Idee, dass es zwei Quellenebenen gibt. Es gibt keine. Sie haben eine Java-Quelle und diese wird zu Java-Byte-Code kompiliert (von der JVM ausgeführt). Dies ist keine zusätzliche Quellebene. Nur weil der Bytecode ein "goto" enthält, heißt das nicht, dass es in Java ein "goto" gibt. Java hat Pausen benannt und wird fortgesetzt, aber kein Goto.
@ tgm1024 Ich wurde durch eine Ablehnung geweckt :) Es kann leicht scheinen, dass ich das Argument verloren habe, seit Sie den letzten Kommentar abgegeben haben und Ihre Anmeldeinformationen beeindruckend sind. Mein Punkt, auf den ich aufgebaut habe, war, dass es sehr gut möglich ist, mit Java-Bytecode zu programmieren. Um Ihnen zu versichern, hier ist sogar eine Frage dazu: stackoverflow.com/questions/3150254/…
Mikael Lindlöf
1

Ich bin auch kein Fan von gotoCode, da dadurch Code normalerweise weniger lesbar wird. Ich glaube jedoch, dass es Ausnahmen von dieser Regel gibt (insbesondere wenn es um Lexer und Parser geht!)

Natürlich können Sie Ihr Programm jederzeit in Kleene Normalform bringen, indem Sie es in etwas Assembler-ähnliches übersetzen und dann etwas Ähnliches schreiben

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

(Sie schreiben also im Grunde eine VM, die Ihren Binärcode ausführt ... wobei dies linedem Anweisungszeiger entspricht.)

Das ist so viel besser lesbar als Code, der verwendet wird goto, nicht wahr?

Viktor Engelmann
quelle
Nächste Frage: "Gibt es eine switch-Anweisung in Python?"
Mark K Cowan
0

Natürlich ist es ein Schlüsselwort, aber es wird nicht auf der Ebene des Quellcodes verwendet.

Wenn Sie jedoch Jasmin oder eine andere niedrigere Sprache verwenden, die in Bytecode umgewandelt wird, ist "goto" vorhanden

user1722245
quelle
-1

Denn obwohl die Java-Sprache es nicht verwendet, tut es JVM-Bytecode.

gribnit
quelle
7
Warum hat die Sprache dann kein loadSchlüsselwort?
Annäherung an
3
@gribnit, ein Goto im Bytecode bedeutet für sich genommen nichts für reservierte Wörter der oberen Ebene.