Есть ли в Java оператор goto?

259

Я запутался в этом. Большинству из нас сказали, что в Java нет операторов goto.

Но я обнаружил, что это одно из ключевых слов в Java. Где это можно использовать? Если его нельзя использовать, то почему он был включен в Java в качестве ключевого слова?

Venkat
источник
13
просто совет: никогда не используйте goto
lostiniceland
16
А затем есть «Перейти к утверждению, которое считается вредным», считается вредным », и« »Перейти к утверждению, которое считается вредным« Считается вредным », считается вредным?» VEEEEERY рекурсивный, этот мем.
Крис Чарабарук
70
«goto» всегда зло - как в «goto work» или «goto school»;)
Андреас Долк
24
Реальная причина в том, что слово "g ** o" считается неприличным в большинстве языков программирования. Java-дизайнеры просто защищают невинных молодых программистов от вредного влияния. (:-))
Стивен С
25
Охота на ведьм против Гото породила некоторые из самых обостряющих моментов в моей жизни. Я видел, как люди искажают код C, скрывая функциональность в функциях, помещая абсурдную логику выхода в многоплановые циклы, и в противном случае делают все возможные формы чрезмерного проектирования просто, чтобы никто не критиковал их код в обзоре кода. Это правило, наряду с слухом «ты должен избегать многократных возвращений», пропитано бессмыслицей. Есть моменты, когда goto делает вещи менее ремонтопригодными. Есть моменты, когда goto делает вещи более ремонтопригодными. Я так надеялся, что эта охота на ведьм погибнет в 80-х.

Ответы:

200

В списке ключевых слов Java указано gotoключевое слово, но оно помечено как «не используется».

Это было в оригинальной JVM (см. Ответ @VitaliiFedorenko ), но затем удалили. Вероятно, оно оставалось в качестве зарезервированного ключевого слова на случай, если оно будет добавлено в более позднюю версию Java.

Если gotoего нет в списке и он будет добавлен к языку позже, существующий код, использующий это слово gotoв качестве идентификатора (имя переменной, имя метода и т. Д.), Сломается. Но поскольку gotoэто ключевое слово, такой код даже не будет компилироваться в настоящее время, и остается возможность заставить его действительно что-то делать позже, не нарушая существующий код.

Томас
источник
29
This was probably done in case it were to be added to a later version of Java.На самом деле главная причина немного другая (см. Мой ответ ниже)
Виталий Федоренко
2
Это хорошая и интересная информация, но она не объясняет, почему это все еще зарезервированное ключевое слово.
Томас
@ Томас Разве вы не описали, почему он зарезервирован? Это ключевое слово, поэтому его нельзя использовать сейчас; позже goto мог ожить без проблем. Если бы это не было зарезервированное слово, оно могло бы теперь использоваться для создания кода (int goto = 2;), который сломался бы, если бы был введен goto.
230

Джеймс Гослинг создал оригинальную JVM с поддержкой gotoутверждений, но затем он удалил эту функцию как ненужную. Основная причина gotoв том, что она не нужна, состоит в том, что обычно ее можно заменить более читаемыми выражениями (например break/continue) или путем извлечения части кода в метод.

Источник: Джеймс Гослинг, сессия вопросов и ответов

Виталий Федоренко
источник
24
«... или путем извлечения части кода в метод» - это должно быть очень круто без надлежащего устранения хвостовых вызовов.
Отображаемое имя
45
Иногда разумное использование goto - самый готовый и понятный способ выразить что-то, поэтому принуждение к чему-либо еще менее читабельно .
дедупликатор
1
@Deduplicator Использование goto, как бы разумно это ни было, всегда подвержено ошибкам.
Челеби Мурат
@Deduplicator Единственное использование goto, которое считается хорошей практикой в ​​C ++, поддерживается перерывом / продолжением.
зима
2
Goto является зарезервированным ключевым словом в Java - это здорово, потому что оно не дает людям называть ярлыки «goto:».
зима
147

Ключевое слово существует, но оно не реализовано.

Единственная веская причина использовать goto, о которой я могу думать, это:

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:

В Java вы можете сделать это следующим образом:

loops:
for (int i = 0; i < MAX_I; i++) {
    for (int j = 0; j < MAX_J; j++) {
        // do stuff
        break loops;
    }
}
jonnystoten
источник
1
@ Zoltán Нет - он перенаправляет код на метку прямо перед первым циклом.
assylias
21
@assylias Ну, не совсем. Этикетка обозначает внешнюю петлю. Затем break loopsозначает «вырваться из цикла называется loops». Возможно, оглядываясь назад, можно было бы найти лучшее название для лейбла outer.
jonnystoten
8
«Единственная хорошая причина использовать goto» Быстрые и грязные маленькие программы, которые нуждаются в безусловном бесконечном цикле, отлично используют goto. Использование while (true) {... }это излишне. GOTO часто подвергается стигматизации за неправильное использование, но я утверждаю, что ненужные сравнения с логическими литералами хуже, чем GOTO.
Александр - Восстановить Монику
1
Разве метка не должна быть после петель?
GC_
1
Недавно я обнаружил, что эта техника маркировки также очень полезна в сочетании с continue LABEL;утверждением. Таким образом, вы можете продолжить внешнюю петлю лжи.
infotoni91
43

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

«Ключевые слова const и goto зарезервированы, хотя в настоящее время они не используются».

Исаак Е
источник
12
"без знака" даже нет! (вздох)
Матье
Имеет смысл, так как все примитивные типы в Java подписаны.
mwieczorek
1
@mwieczorek Не все. «char» - это примитивный тип, и он без знака.
Сергей Кривенков
29

Таким образом, их можно было бы использовать однажды, если бы дизайнеры языка почувствовали необходимость.

Кроме того, если программисты из языков, которые имеют эти ключевые слова (например, C, C ++), используют их по ошибке, то компилятор Java может выдать полезное сообщение об ошибке.

Или, может быть, это было просто, чтобы остановить программистов, использующих goto :)

Дейв
источник
Отсутствующая функциональность goto в Java должна быть достаточной причиной, чтобы не использовать goto - нет необходимости резервировать ее как ключевое слово. Следуя вашей логике, все будет ключевым словом, поскольку оно будет использоваться другими языками и / или разработчики Java МОГУТ использовать его в будущем ...
stuXnet
1
Я не думаю, что моя логика подразумевает, что все будет ключевым словом. Во многих языках программирования используется небольшой набор ключевых слов, которые можно с пользой обнаружить и обработать в Java. Java зарезервирована gotoи constотражает ее наследие C / C ++, но они остаются нереализованными (хотя были споры о реализации последнего). Пара больше понравилась assertи enumизначально не была зарезервирована, но, возможно, следовало бы, учитывая, что они были реализованы. Но задним числом это замечательная вещь.
Дейв
19

Они зарезервированы для будущего использования (см .: Ключевые слова языка Java )

Ключевые слова const и goto зарезервированы, хотя в настоящее время они не используются.

Причину, по которой в Java нет оператора goto, можно найти в разделе «Языковая среда Java »:

У Java нет оператора goto. Исследования показали, что goto (неправильно) используется чаще, чем просто «потому что оно есть». Исключение goto привело к упрощению языка - например, нет никаких правил относительно воздействия goto на середину оператора for. Исследования примерно 100 000 строк кода на C показали, что примерно 90 процентов операторов goto были использованы исключительно для получения эффекта разрыва вложенных циклов. Как уже упоминалось выше, многоуровневый разрыв и продолжение устраняют большую часть необходимости в операторах goto.

Heinzi
источник
gotoЗарезервировано, но не для будущего использования.
Маркиз Лорн
17

Пример использования меток «продолжить» в 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);
    }
}

Полученные результаты:

I am here // i=0
j: 0
j: 1
I am here // i=1
I am here // i=2
temp = 1
Андрей
источник
10

Важно понимать, что gotoконструкция является остатком тех дней, когда программисты программировали на машинном коде и ассемблере. Поскольку эти языки настолько просты (как, например, каждая инструкция выполняет только одно ), процесс управления программой полностью выполняется с помощью gotoоператоров (но на языке ассемблера они называются инструкциями перехода или перехода ).

Теперь, хотя язык C довольно низкоуровневый, его можно рассматривать как язык ассемблера очень высокого уровня - каждое утверждение и функция в C могут быть легко разбиты на инструкции на языке ассемблера. Хотя C сегодня не является основным языком программирования компьютеров, он все еще широко используется в приложениях низкого уровня, таких как встроенные системы. Поскольку функция C настолько близко отражает функцию ассемблера, имеет смысл только то, что gotoвключено в C.

Понятно, что Java - это эволюция C / C ++. Java имеет много функций из C, но абстрагирует намного больше деталей, и поэтому просто написано по-другому. Java - это язык очень высокого уровня, поэтому просто нет необходимости иметь низкоуровневые функции, например, gotoкогда более высокоуровневые конструкции, такие как функции, для каждого, и в то время как циклы выполняют поток управления программой. Представьте, что вы были в одной функции и сделали gotoметку для другой функции. Что произойдет, когда другая функция вернется? Эта идея абсурдна.

Это не обязательно объясняет, почему Java включает gotoоператор, но не позволяет его компилировать, но важно знать, почему оно gotoвообще использовалось, в приложениях более низкого уровня, и почему просто не имеет смысла используется в Java.

Майкл П в NCSU
источник
msgstr "поток управления программой полностью выполнен с помощью goto". Ну, не всегда безоговорочный гото.
Питер Мортенсен
Переход с «goto» из одной функции в метку в другой функции также невозможен в C / C ++. Goto в C / C ++ ограничен одним функциональным блоком.
user2328447
«просто нет необходимости иметь низкоуровневые функции, такие как goto, когда более высокоуровневые конструкции», - помните «Необходимость и достаточность». Это просто «не обязательно». И поэтому нет причин. Что является причиной: «Goto» как «высокоуровневый» заменитель JMP, BNE и других в Ассемблере является разумным, если вы хотите перейти к «исполняемому коду», но Java является байт-кодом и, следовательно, не «исполняемым». ;-)
Рейххарт
10

Нет, gotoне используется, но вы можете определить метки и оставить цикл до метки. Вы можете использовать breakили continueследовать метки. Таким образом, вы можете выпрыгнуть более чем на один уровень цикла. Взгляните на учебник .

Арне Бурмейстер
источник
9

Нет, к счастью, нет gotoв Java.

gotoКлючевое слово только зарезервирован, но не используется (то же самое касается const).

Bozho
источник
Могу ли я узнать, что здесь подразумевается под зарезервированным? Если использование goto и const в коде не является хорошей практикой, почему они резервируют это? Не могли бы вы объяснить?
Гопи
@ Шри Кумар: смотрите ответ @ applechewer, он существует, но он не реализован.
Валентин Роше
1
@ Шри Кумар: зарезервированные ключевые слова не позволяют использовать их в качестве имен переменных или аналогичных. Таким образом, эти ключевые слова могут быть реализованы в будущих версиях Java, не нарушая старый исходный код, который мог бы использовать их в противном случае.
Питер Ди Чекко
8

Потому что это не поддерживается и зачем вам gotoключевое слово, которое ничего не делало, или переменная с именемgoto ?

Хотя вы можете использовать break label;и continue label;заявления, чтобы эффективно делать то, что gotoделает. Но я бы не рекомендовал это.

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 Почему мне нельзя разрешить иметь переменную или метод с именем goto?
Майкл Боргвардт
4
Потому что это имеет значение в области программирования, которая не применима к Java. Это также плохой выбор имени переменной.
pjp
Для чего будет использоваться переменная print? Упомянутые вами слова больше похожи на имена методов, чем на переменные или ключевые слова.
pjp
3
-1: Прежде всего, то, что Java не поддерживает оператор управления потоком «goto», не означает, что по этой причине у него есть ключевое слово «goto», которое ничего не делает. Во-вторых, «goto» может быть плохим именем переменной, но это может быть отличное имя метода, которое мы не можем использовать, потому что «goto» является ключевым словом. В-третьих, «перерыв метки» и «продолжение метки» существуют по очень веской причине, поэтому «не рекомендовать это» не очень полезно. И в-четвертых, поскольку Sun говорит, что он «в настоящее время не используется», это, скорее всего, означает, что они когда-то планировали реализовать, но не хотели избавляться от ключевого слова, когда решили иначе.
Воислав Стойкович
2
@VojislavStojkovic Это просто сумасшедший разговор. 1) То есть , почему он ничего не делает , потому что он не поддерживает его. В соответствии с 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.это означает: «Мы не используем его, поэтому, если вы пришли из C ++, мы вообще не позволим вам его использовать». 2) gotoужасное название метода. Сожалею. 3) рекомендуется прервать и продолжить, но не так, как здесь . 4) «скорее всего».
CorsiKa
7

Нет, gotoне используется в Java, хотя является зарезервированным словом. То же самое верно для const. Оба они используются в C ++, что, вероятно, является причиной того, что они зарезервированы; Цель заключалась в том, чтобы избежать путаницы программистов на C ++, мигрирующих на Java, и, возможно, также оставить возможность использовать их в более поздних версиях Java.

Майкл Боргвардт
источник
1
Я действительно надеюсь, gotoчто не будет поддержан в ближайшем будущем, по крайней мере;)
Божо
6
@ Божо: ну, это может быть использовано для какой-то гениальной новой функции, которая не имеет абсолютно ничего общего с плохим старым "вредным" переходом.
Майкл Боргвардт
3

Обратите внимание, что вы можете заменить большинство доброкачественных применений goto на

  • возвращение

  • перерыв

  • сломать ярлык

  • бросить внутрь попробовать-поймать-наконец

starblue
источник
5
Исключения никогда не должны использоваться для управления потоком
ChssPly76
13
Исключения будут использоваться для управления потоком, но их следует использовать только в исключительных случаях. Например, одно из применений goto в C - обработка ошибок, особенно если это включает очистку.
звездный синий
2
@starblue, ты вынул слова из моих уст. Бросок исключения - это поток управления. На самом деле, в C вы можете довольно просто реализовать обработку исключений через setjmp / longjmp, убедившись, что сначала вы установили setjmp для кода обработки и выполнили longjmp () для него в случае исключения.
Я хочу сделать проверку if и пропустить половину метода, если true. Без перехода я должен использовать гигантский еще. ИМО, это довольно некрасиво, так как слишком большое количество споров приводит к путанице
WVrock
1
@WVrock Вы можете попробоватьreturn
Эндрю Лазарь
2

Как указывалось, gotoв Java его нет, но ключевое слово было зарезервировано на случай, если Sun захочет добавить gotoв Java один день. Они хотели иметь возможность добавлять его, не нарушая слишком много кода, поэтому они зарезервировали ключевое слово. Обратите внимание, что в Java 5 они добавили enumключевое слово, и оно не сломало много кода.

Хотя у Java этого нет goto, у него есть некоторые конструкции, которые соответствуют некоторым применениям goto, а именно, возможность использовать breakи continueс именованными циклами. Кроме того, finallyможно думать как своего рода витой goto.

Томас Порнин
источник
1

Запретить объявления переменных с одинаковыми именами.

например int i = 0, goto;

Карл
источник
3
Но почему ? Почему бы нам не позволить сделать эти заявления?
Приближается к
1

Это очень часто считается одной из тех вещей, которые вы не делаете, но, вероятно, было указано в качестве зарезервированного слова, чтобы избежать путаницы для разработчиков.

Дин Дж
источник
1

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

Если вам сказали, что в Java нет оператора goto, вас одурачили. Действительно, Java состоит из двух уровней «исходного» кода.

Микаэль Линдлоф
источник
5
это все равно что сказать, что у любого языка есть goto, потому что под всем этим кодом в ассемблере существует безусловная ветвь. Наличие goto в байт-коде не означает, что в java есть goto, потому что «в java» означает «на языке java», а байт-код не является слоем исходного кода.
@ tgm1024, «в Java» также можно интерпретировать как «в платформе Java». Компилятору Java необходимо создать байт-код Java, иначе выходные данные не будут работать на платформе Java JVM. C ++, например, не указывает выходные данные компиляции, и компилятор может создавать любую форму машинного кода (или любой другой код). Приложение, запрограммированное байт-кодом Java, можно назвать «приложением Java», но приложение, запрограммированное машинным кодом, нельзя назвать «приложением C ++».
Микаэль Линдлоф,
2
Я прекрасно знаю, что такое Java-байт-код. Я впервые начал писать в java в 1996 году. И другие языки могут генерировать байт-код java для JVM. То, что я исправляю вас, это идея, что есть два уровня источника. Отсутсвуют. У вас есть исходный код Java, и он скомпилирован в байт-код Java (выполняется JVM), и это не дополнительный уровень исходного кода. То, что в байт-коде есть «goto», не означает, что в java есть «goto». Java назвала breaks, а named продолжается, но не переходил.
@ tgm1024 Я был разбужен подавленным голосом :) Может показаться, что я проиграл спор, так как вы сделали последний комментарий, и ваши полномочия впечатляют. Моя точка зрения, которую я строил, заключалась в том, что очень возможно программировать с помощью байт-кода Java. Уверяю вас, вот даже вопрос об этом: stackoverflow.com/questions/3150254/…
Микаэль Линдлоф
1

Смотрите следующую ссылку, показывает все зарезервированные слова Java и говорит вам, какие версии они были добавлены.

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

goto зарезервировано, хотя в настоящее время оно не используется, однако никогда не говорите никогда :)

Пол Уилан
источник
1

Я не фанат gotoни того, ни другого, поскольку это обычно делает код менее читабельным. Однако я верю, что есть исключения из этого правила (особенно когда речь идет о лексерах и парсерах!)

Конечно, вы всегда можете перенести свою программу в Kleene Normalform, переведя ее в нечто, похожее на ассемблер, а затем написать что-то вроде

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

(Таким образом, вы в основном пишете виртуальную машину, которая выполняет ваш двоичный код ... где lineсоответствует указателю инструкции)

Это гораздо более читабельно, чем код, который использует goto, не так ли?

Виктор Энгельманн
источник
Следующий вопрос: «Есть ли в Python оператор switch»
Марк К Коуэн,
0

Конечно, это ключевое слово, но оно не используется на уровне исходного кода.

Но если вы используете jasmin или другой язык более низкого уровня, который преобразуется в байт-код, тогда "goto" есть

user1722245
источник
-1

Потому что, хотя язык Java не использует его, байт-код JVM делает это.

gribnit
источник
7
Тогда почему у языка нет loadключевого слова?
Приближается к
3
@gribnit, наличие goto в байт-коде само по себе ничего не значит для зарезервированных слов верхнего уровня.