Czy istnieje instrukcja goto w Javie?

259

Jestem tym zmieszany. Większość z nas została poinformowana, że ​​w Javie nie ma goto.

Ale odkryłem, że jest to jedno ze słów kluczowych w Javie. Gdzie można go użyć? Jeśli nie można go użyć, to dlaczego został uwzględniony w Javie jako słowo kluczowe?

Venkat
źródło
13
tylko jedna rada: nigdy nie używaj goto
lostiniceland
16
A potem jest „Idź do oświadczenia uważany za szkodliwy” Uważany za szkodliwy ”i„ ”„ Idź do oświadczenia uważany za szkodliwy ”Uważany za szkodliwy„ Uważany za szkodliwy? ” VEEEEERY rekurencyjny, ten mem.
Chris Charabaruk
70
„goto” jest zawsze złe - jak w „goto work” lub „goto school”;)
Andreas Dolk
24
Prawdziwym powodem jest to, że słowo „g ** o” jest uważane za nieprzyzwoite w większości języków programowania. Projektanci Java chronią tylko niewinnych młodych programistów przed niszczącymi wpływami. (:-))
Stephen C
25
Polowanie na czarownice przeciwko Goto zrodziło jedne z najbardziej irytujących momentów w moim życiu. Widziałem ludzi zniekształcających kod C, ukrywających funkcjonalność w funkcjach, umieszczających absurdalną logikę wyjścia w wielo-zagnieżdżonych pętlach, a poza tym wykonujących wszelkie formy nadmiaru inżynierii, jakie tylko można sobie wyobrazić, aby nikt nie krytykował ich kodu w przeglądzie kodu. Ta zasada, wraz z kartą „musisz unikać wielokrotnych zwrotów”, jest przesiąknięta nonsensem. Są chwile, kiedy goto sprawia, że ​​rzeczy są mniej konserwowalne. Są chwile, kiedy goto sprawia, że ​​rzeczy są łatwiejsze w utrzymaniu. Miałem nadzieję, że to polowanie na czarownice umrze w latach 80-tych.

Odpowiedzi:

200

Na listę Java słowa kluczowe określa gotosłowo kluczowe, ale to jest oznaczone jako „nieużywane”.

To było w oryginalnej JVM (patrz odpowiedź @VitaliiFedorenko ), ale potem zostało usunięte. Prawdopodobnie był przechowywany jako zastrzeżone słowo kluczowe na wypadek, gdyby miał zostać dodany do późniejszej wersji Javy.

Gdyby gotonie było jej na liście, a później zostanie dodane do języka, istniejący kod, który użył tego słowa gotojako identyfikatora (nazwa zmiennej, nazwa metody itp.) Zepsułby się. Ale ponieważ gotojest słowem kluczowym, taki kod nawet się nie skompiluje w teraźniejszości i nadal można sprawić, że zrobi coś później, bez niszczenia istniejącego kodu.

Tomasz
źródło
29
This was probably done in case it were to be added to a later version of Java.Właściwie główny powód jest nieco inny (patrz moja odpowiedź poniżej)
Vitalii Fedorenko
2
To dobra i interesująca informacja, ale nie wyjaśnia, dlaczego wciąż jest zastrzeżonym słowem kluczowym.
Thomas
@ Thomas Nie opisałeś, dlaczego jest zarezerwowany? To słowo kluczowe, więc nie można go teraz użyć; później goto mógł powstać bez powodowania problemów. Gdyby nie było słowa zarezerwowanego, mogłoby być teraz użyte do wygenerowania kodu (int goto = 2;), który pękłby, gdyby wprowadzono goto.
230

James Gosling stworzył oryginalną maszynę JVM przy wsparciu gotoinstrukcji, ale potem usunął tę funkcję jako niepotrzebną. Główny powód gotojest niepotrzebny, ponieważ zwykle można go zastąpić bardziej czytelnymi instrukcjami (jak break/continue) lub wyodrębnić fragment kodu do metody.

Źródło: James Gosling, sesja pytań i odpowiedzi

Vitalii Fedorenko
źródło
24
„... lub przez wyodrębnienie fragmentu kodu do metody” - to musi być bardzo fajne bez odpowiedniej eliminacji wywołania ogona.
Nazwa wyświetlana
45
Czasami rozsądne użycie goto jest najbardziej gotowym i jasnym sposobem wyrażenia czegoś, więc zmuszanie go do czegokolwiek innego jest bardzo mało czytelne .
Deduplicator
1
@Deduplicator Korzystanie z goto, jakkolwiek rozsądne, zawsze jest podatne na błędy.
Çelebi Murat
@Deduplicator Jedyne użycie goto uważanego za dobrą praktykę w C ++ jest wspierane przez przerwanie / kontynuowanie.
Zima
2
Goto jest zarezerwowanym słowem kluczowym w Javie, jest świetne, ponieważ uniemożliwia nazwanie etykiet „goto:”.
Zima
147

Słowo kluczowe istnieje, ale nie zostało zaimplementowane.

Jedyny dobry powód, aby użyć goto, o którym mogę myśleć, to:

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:

W Javie możesz to zrobić w następujący sposób:

loops:
for (int i = 0; i < MAX_I; i++) {
    for (int j = 0; j < MAX_J; j++) {
        // do stuff
        break loops;
    }
}
jonnystoten
źródło
1
@ Zoltán Nie - przekierowuje kod do etykiety tuż przed pierwszą pętlą.
assylias
21
@assylias Cóż, niezupełnie. Etykieta oznacza zewnętrzną pętlę. Następnie break loopsśrodki „wyrwać się z pętli o nazwie loops”. Może z perspektywy czasu mogłaby być lepsza nazwa etykiety outer.
jonnystoten
8
„Jedyny dobry powód, aby użyć goto” Szybkie i brudne małe programy, które wymagają bezwarunkowej nieskończonej pętli, świetnie wykorzystują goto. Używanie while (true) {... }to przesada. GOTO jest często napiętnowane z powodu niewłaściwego użycia, ale twierdzę, że niepotrzebne porównania z literałami logicznymi są gorsze niż GOTO.
Alexander - Przywróć Monikę
1
Czy etykieta pętli nie powinna znajdować się po pętlach?
GC_
1
Niedawno odkryłem, że ta technika znakowania jest również bardzo przydatna w połączeniu z continue LABEL;oświadczeniem. W ten sposób możesz kontynuować zewnętrzną pętlę leżącą.
infotoni91
43

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

„Słowa kluczowe const i goto są zastrzeżone, nawet jeśli nie są obecnie używane”.

Izaak E.
źródło
12
„bez znaku” nawet tam nie ma! (westchnienie)
Matthieu
Ma to sens, ponieważ wszystkie pierwotne typy w Javie są podpisane.
mwieczorek,
1
@mwieczorek Nie wszystkie. „char” jest prymitywnym typem i jest niepodpisane.
Sergey Krivenkov
29

Mogą więc zostać wykorzystane pewnego dnia, jeśli projektanci języków poczują taką potrzebę.

Ponadto, jeśli programiści z języków, które mają te słowa kluczowe (np. C, C ++) używają ich przez pomyłkę, to kompilator Java może dać użyteczny komunikat o błędzie.

A może po prostu przestało programiści używać goto :)

Dave
źródło
Brak funkcji goto w Javie powinien być wystarczającym powodem, aby nie używać goto - nie trzeba rezerwować go jako słowa kluczowego. Zgodnie z logiką wszystko będzie słowem kluczowym, ponieważ jest używane przez inne języki i / lub projektanci Java MOGĄ używać go w przyszłości ...
stuXnet
1
Nie sądzę, że moja logika sugeruje, że wszystko byłoby słowem kluczowym. W wielu językach programowania używany jest niewielki zestaw słów kluczowych, które można z łatwością wykryć i obsługiwać w Javie. Java zarezerwowała gotoi constodzwierciedla swoje dziedzictwo C / C ++, ale pozostają one niezaimplementowane (chociaż dyskutowano o ich wdrożeniu). Kilka innych podobnych asserti enumpoczątkowo nie było zarezerwowanych, ale być może powinno, ponieważ zostały wdrożone. Ale z perspektywy czasu to cudowna rzecz.
dave
19

Są zastrzeżone do użytku w przyszłości (patrz: Słowa kluczowe języka Java )

Słowa kluczowe const i goto są zastrzeżone, nawet jeśli nie są obecnie używane.

Powód, dla którego nie ma instrukcji goto w Javie, można znaleźć w „ The Java Language Environment ”:

Java nie ma instrukcji goto. Badania pokazały, że goto jest (źle) używane częściej niż nie tylko „ponieważ tam jest”. Wyeliminowanie goto doprowadziło do uproszczenia języka - na przykład nie ma żadnych zasad dotyczących efektów goto w środku instrukcji for. Badania około 100 000 wierszy kodu C wykazały, że około 90 procent instrukcji goto zostało wykorzystanych wyłącznie w celu uzyskania efektu przerwania zagnieżdżonych pętli. Jak wspomniano powyżej, wielopoziomowy podział i kontynuacja usuwają większość potrzeby instrukcji goto.

Heinzi
źródło
gotojest zastrzeżone, ale nie do wykorzystania w przyszłości.
Markiz Lorne
17

Przykładem użycia etykiet „kontynuuj” w Javie jest:

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

Wyniki:

I am here // i=0
j: 0
j: 1
I am here // i=1
I am here // i=2
temp = 1
Andrzej
źródło
10

Ważne jest, aby zrozumieć, że gotokonstrukcja jest pozostałością po dniach, w których programiści programowali w kodzie maszynowym i języku asemblera. Ponieważ te języki są tak podstawowe (jak w, każda instrukcja robi tylko jedną rzecz), przepływ sterowania programem odbywa się całkowicie za pomocą gotoinstrukcji (ale w języku asemblera są one nazywane skokami lub rozgałęzieniami instrukcjami ).

Teraz, chociaż język C jest dość niskim poziomem, można go traktować jako bardzo asemblerowy język asemblera - każdą instrukcję i funkcję w C można łatwo podzielić na instrukcje języka asemblerowego. Chociaż C nie jest obecnie głównym językiem do programowania komputerów, nadal jest intensywnie wykorzystywany w aplikacjach niskiego poziomu, takich jak systemy wbudowane. Ponieważ funkcja C tak ściśle odzwierciedla funkcję języka asemblera, ma to sensgoto jest uwzględniona w C.

Oczywiste jest, że Java jest ewolucją C / C ++. Java ma wiele funkcji z C, ale wyodrębnia znacznie więcej szczegółów i dlatego jest po prostu napisana inaczej. Java jest językiem bardzo wysokiego poziomu, więc po prostu nie jest konieczne posiadanie funkcji niskiego poziomu, na przykład gotogdy więcej konstruktów wyższego poziomu, takich jak funkcje, dla każdego z nich, a podczas pętli podczas sterowania programem. Wyobraź sobie, że byłeś w jednej funkcji i zrobiłeś gotoetykietę innej funkcji. Co by się stało, gdy druga funkcja powróci? Ten pomysł jest absurdalny.

To niekoniecznie odpowiada, dlaczego Java zawiera gotoinstrukcję, ale nie pozwala jej na kompilację, ale ważne jest, aby wiedzieć, dlaczego w gotoogóle była używana w aplikacjach niższego poziomu i dlaczego po prostu nie ma sensu być używane w Javie.

Michael P. w NCSU
źródło
„przepływ sterowania programem odbywa się całkowicie za pomocą goto”. Cóż, nie zawsze bezwarunkowe goto.
Peter Mortensen
Skakanie z „goto” z jednej funkcji do etykiety w innej funkcji również nie jest możliwe w C / C ++. Goto w C / C ++ jest ograniczone do jednego bloku funkcyjnego.
user2328447,
„po prostu nie trzeba mieć funkcji niskiego poziomu, takich jak goto, gdy więcej konstrukcji wysokiego poziomu” - pamiętaj „Konieczność i wystarczalność”. To po prostu „niepotrzebne”. I dlatego nie ma powodu. Jaki jest powód: „Goto” jako „wysoki poziom” zamiennik JMP, BNE i więcej Assemblera jest rozsądny, jeśli chcesz przejść do „kodu wykonywalnego”, ale Java jest kodem bajtowym, a zatem nie „wykonywalnym”. ;-)
reichhart
10

Nie, gotonie jest używane, ale można zdefiniować etykiety i pozostawić pętlę do etykiety. Możesz użyć etykiety breaklub continuepo niej. Możesz więc wyskoczyć z więcej niż jednego poziomu pętli. Spójrz na samouczek .

Arne Burmeister
źródło
9

Nie, na szczęście nie ma goto Java.

Słowo gotokluczowe jest zastrzeżone, ale nie używane (to samo dotyczy const).

Bozho
źródło
Czy mogę wiedzieć, co oznacza tutaj zarezerwowany? Jeśli używanie goto i const w kodzie nie jest dobrą praktyką, dlaczego go rezerwują? Czy możesz wyjaśnić?
Gopi,
@Sri Kumar: patrz odpowiedź @ applechewer, istnieje, ale nie jest zaimplementowana.
Valentin Rocher
1
@Sri Kumar: Zarezerwowane słowa kluczowe zapobiegają używaniu ich jako nazw zmiennych lub podobnych. W ten sposób te słowa kluczowe mogą zostać zaimplementowane w przyszłych wersjach Javy bez zerwania starego kodu źródłowego, który mógłby ich użyć.
Peter Di Cecco
8

Ponieważ nie jest obsługiwany i dlaczego chcesz mieć gotosłowo kluczowe, które nic nie robiło lub zmienną o nazwiegoto ?

Chociaż możesz użyć break label;i continue label;instrukcji, aby skutecznie robić to, co gotorobi. Ale nie poleciłbym tego.

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
źródło
10
-1 Dlaczego nie wolno mi mieć zmiennej lub metody o nazwie goto?
Michael Borgwardt
4
Ponieważ ma to znaczenie w krainie programowania, która nie dotyczy Java. Jest to również zły wybór nazwy zmiennej.
pjp
Do czego byłaby używana zmienna „druk”? Słowa, które wspomniałeś, bardziej przypominają nazwy metod niż zmienne lub słowa kluczowe.
pjp
3
-1: Po pierwsze, fakt, że Java nie obsługuje instrukcji kontroli przepływu „goto”, nie oznacza, że ​​jest to powód, dla którego ma słowo kluczowe „goto”, które nic nie robi. Po drugie, „goto” może być kiepską nazwą zmiennej, ale może być doskonałą nazwą metody, której nie możemy użyć, ponieważ „goto” jest słowem kluczowym. Po trzecie, „break label” i „Continue label” istnieją z bardzo dobrego powodu, więc „niezalecanie” nie jest zbyt przydatne. I po czwarte, ponieważ Sun mówi, że „nie jest obecnie używany”, najprawdopodobniej oznacza to, że kiedyś planowali wdrożyć, ale nie chcieli pozbyć się słowa kluczowego, gdy zdecydowali inaczej.
Vojislav Stojkovic
2
@VojislavStojkovic To tylko szalona rozmowa. 1) To jest , dlaczego nic nie robi to dlatego, że jej nie obsługuje. Według 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.Oznacza to: „Nie używamy go, więc jeśli pochodzisz z języka C ++, nie pozwolimy ci go w ogóle używać”. 2) gototo okropna nazwa metody. Przepraszam. 3) zalecane jest przerwanie i kontynuacja, ale nie w sposób tutaj użyty . 4) „najprawdopodobniej” [potrzebne źródło].
corsiKa
7

Nie, gotonie jest używany w Javie, mimo że jest słowem zastrzeżonym. To samo dotyczy const. Oba są używane w C ++, co prawdopodobnie jest powodem, dla którego są zastrzeżone; intencją było prawdopodobnie uniknięcie mylących programistów C ++ migrujących do Javy, a być może także zachowanie opcji ich używania w późniejszych wersjach Javy.

Michael Borgwardt
źródło
1
Naprawdę mam nadzieję, że gotonie będzie obsługiwany przynajmniej w najbliższej przyszłości;)
Bozho
6
@Bozho: cóż, można go użyć do jakiejś genialnej nowej funkcji, która absolutnie nie ma nic wspólnego ze starym, złym „szkodliwym” goto.
Michael Borgwardt
3

Zauważ, że możesz zastąpić większość łagodnych zastosowań goto przez

  • powrót

  • przerwa

  • złamać etykietę

  • wrzuć do środka try-catch-wreszcie

starblue
źródło
5
NIGDY nie należy używać do kontroli przepływu
ChssPly76
13
Wyjątki stosowane do kontroli przepływu, ale powinny być stosowane tylko w wyjątkowych przypadkach. Na przykład jednym z zastosowań goto w C jest obsługa błędów, zwłaszcza jeśli wymaga czyszczenia.
starblue
2
@starblue, wyjąłeś słowa z moich ust. Zgłoszenie wyjątku to przepływ kontrolny. W rzeczywistości w C można w pewien sposób czysto zaimplementować obsługę wyjątków za pomocą setjmp / longjmp, upewniając się, że najpierw ustawiłeś kod obsługi i wykonałeś na nim funkcję longjmp ().
Chcę wykonać sprawdzenie if i pominąć połowę metody, jeśli jest to prawda. Bez pójścia do niego muszę użyć giganta. IMO jest dość brzydka, ponieważ zbyt wiele nawiasów powoduje zamieszanie
WVrock,
1
@WVrock Możesz spróbowaćreturn
Andrew Lazarus
2

Jak już wspomniano, gotoJava nie istnieje , ale słowo kluczowe zostało zarezerwowane na wypadek, gdyby Sun miał ochotę dodać coś gotodo Javy. Chcieli mieć możliwość dodania go bez łamania zbyt dużej ilości kodu, więc zarezerwowali słowo kluczowe. Zauważ, że w Javie 5 dodali enumsłowo kluczowe i nie złamało to zbyt wiele kodu.

Chociaż Java nie ma goto, ma pewne konstrukcje, które odpowiadają niektórym zastosowaniom goto, a mianowicie możliwość breaki continuenazwane pętle. Ponadto, finallymogą być traktowane jako rodzaj skręcona goto.

Thomas Pornin
źródło
1

Aby zabronić deklaracji zmiennych o tej samej nazwie.

na przykład int i = 0, goto;

Karl
źródło
3
Ale dlaczego ? Dlaczego nie wolno nam składać takich deklaracji?
ApproachingDarknessFish
1

Jest bardzo uważany za jedną z rzeczy, których nie robisz, ale prawdopodobnie został wymieniony jako słowo zastrzeżone, aby uniknąć nieporozumień dla programistów.

Dziekan J.
źródło
1

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

Jeśli powiedziano ci, że nie ma instrukcji goto w Javie, zostałeś oszukany. Rzeczywiście, Java składa się z dwóch warstw kodu „źródłowego”.

Mikael Lindlöf
źródło
5
to tak, jakby powiedzieć, że każdy język ma goto, ponieważ pod nim znajduje się bezwarunkowa gałąź w kodzie asemblera. Posiadanie goto w kodzie bajtowym nie oznacza, że ​​jest goto w java, ponieważ „in java” oznacza „w języku java”, a kod bajtu nie jest warstwą źródłową.
@ tgm1024, „in Java” można również interpretować jako „in Java platform”. Kompilator Java musi wygenerować kod bajtowy Java, w przeciwnym razie dane wyjściowe nie będą działać w JVM platformy Java. Na przykład C ++ nie określa danych wyjściowych kompilacji, a kompilator może dowolnie tworzyć dowolny kod maszynowy (lub inny kod). Aplikację zaprogramowaną na kod bajtowy Java można nazwać „aplikacją Java”, ale aplikacji zaprogramowanej kodem maszynowym nie można nazwać „aplikacją C ++”.
Mikael Lindlöf,
2
Wiem doskonale, co to jest kod bajtowy java. Po raz pierwszy kodowałem w Javie w 1996 roku. I możesz mieć inne języki generujące kod bajtowy Java dla JVM. Poprawiam cię w tym, że istnieją dwie warstwy źródła. Nie ma. Masz źródło Java, które jest kompilowane do kodu bajtu Java (wykonywanego przez JVM) i nie jest to dodatkowa warstwa źródła. To, że w kodzie bajtów jest „goto”, nie oznacza, że ​​w java jest „goto”. Java nazwała przerwy i nazwa kontynuuje, ale nie ma goto.
@ tgm1024 Zostałem obudzony przez opinię negatywną :) Może się wydawać, że zgubiłem argument, ponieważ napisałeś ostatni komentarz, a twoje dane uwierzytelniające są imponujące. Chodziło mi o to, że do tego dążyłem, że programowanie za pomocą kodu bajtowego Java jest bardzo możliwe. Aby Cię zapewnić, oto nawet pytanie na ten temat: stackoverflow.com/questions/3150254/...
Mikael Lindlöf
1

Nie jestem ich fanem goto, ponieważ zwykle sprawia, że ​​kod jest mniej czytelny. Uważam jednak, że istnieją wyjątki od tej reguły (szczególnie jeśli chodzi o leksyki i parsery!)

Oczywiście zawsze możesz przenieść swój program do Kleene Normalform, tłumacząc go na coś podobnego do asemblera, a następnie napisać coś takiego

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

(Więc w zasadzie piszesz maszynę wirtualną, która wykonuje kod binarny ... gdzie lineodpowiada wskaźnikowi instrukcji)

To jest o wiele bardziej czytelne niż kod, który używa goto, prawda?

Viktor Engelmann
źródło
Następne pytanie: „Czy w Pythonie jest instrukcja zamiany”
Mark K Cowan,
0

Oczywiście jest to słowo kluczowe, ale nie jest używane na poziomie kodu źródłowego.

Ale jeśli używasz języka jasmin lub innego języka niższego poziomu, który jest przekształcany do kodu bajtowego, wtedy „goto” jest dostępne

użytkownik1722245
źródło
-1

Ponieważ chociaż język Java go nie używa, robi to kod bajtowy JVM.

gribnit
źródło
7
Dlaczego więc język nie ma loadsłowa kluczowego?
ApproachingDarknessFish
3
@gribnit, posiadanie goto w kodzie bajtowym samo w sobie nie znaczy niczego dla słów zarezerwowanych na wyższym poziomie.