Чи є у Java заява goto?


259

Мене з цим бентежить. Більшості з нас сказали, що на Java немає жодної заяви goto.

Але я виявив, що це одне з ключових слів на Java. Де його можна використовувати? Якщо його не можна використовувати, то чому він був включений у Java як ключове слово?


13
лише слово поради: ніколи не використовуйте goto
lostiniceland

16
А потім "" Перейти до заяви вважається шкідливим "вважається шкідливим" та "" Перейти до заяви вважається шкідливим "вважається шкідливим" вважається шкідливим? " VEEEEERY рекурсивний, цей мем.
Кріс Чарабарук,

70
'goto' завжди зло - як у 'goto work' або 'goto school';)
Андреас Долк

24
Справжня причина полягає в тому, що слово "g ** o" вважається непристойним у більшості мов програмування. Дизайнери Java просто захищають невинних молодих програмістів від корупційних впливів. (:-))
Стівен C

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
Це гарна і цікава інформація, але вона не пояснює, чому це все-таки зарезервоване ключове слово.
Томас

@Thomas Ви не описали, чому це зарезервовано? Це ключове слово, тому його зараз не можна використовувати; пізніше гото може почати життя, не створюючи проблем. Якби це не було зарезервоване слово, воно може бути використане зараз для створення коду (int goto = 2;), який би зламався, якщо вводити goto.

230

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

Джерело: Джеймс Гослінг, сесія з питань запитання


24
"... або шляхом вилучення фрагмента коду в метод" - це повинно бути дуже здорово без належного усунення хвостового виклику.
Відображення імені

45
Іноді розумне використання goto - це найбільш готовий і зрозумілий спосіб висловити щось, тому примушувати його до чого-небудь іншого є менш зрозумілим .
Дедуплікатор

1
@Deduplicator Використання goto, розумного, як це може бути, завжди схильне до помилок.
Çelebi Murat

@Deduplicator Єдине використання goto, яке вважається гарним спілкуванням у C ++, підтримується перервою / продовженням.
Зимовий

2
Гото бути зарезервованим ключовим словом на 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;
    }
}

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 можна знайти в « The Java Language Environment »:

У Java немає goto-заяви. Дослідження ілюструють, що гото (помилково) використовується частіше, ніж просто, "оскільки воно є". Усунення goto призвело до спрощення мови - наприклад, немає правил щодо ефектів goto в середині виразного запису, наприклад. Дослідження приблизно на 100 000 рядків коду С визначили, що приблизно 90 відсотків операторів goto використовуються виключно для отримання ефекту прориву вкладених циклів. Як було сказано вище, багаторівневий перерву та продовження усувають більшість потреб у операторах goto.


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 настільки віддзеркалює функцію мови складання, вона має сенс gotoлише включити її в C.

Зрозуміло, що Java - це еволюція C / C ++. Java має багато функцій від C, але абстрагує набагато більше деталей, а тому просто пишеться по-іншому. Java є дуже високим рівнем мови, тому просто не потрібно мати функції низького рівня, наприклад, gotoколи більш високі рівні конструюють, як функції, для кожної, і в той час як циклі виконують потік управління програмою. Уявіть, якби ви були в одній функції та робили gotoмітку для іншої функції. Що буде, коли інша функція повернеться? Ця думка абсурдна.

Це не обов'язково відповідає тому, чому Java включає gotoзаяву, але вона не дозволить її складати, але важливо знати, чому gotoвона коли-небудь використовувалася, в додатках нижчого рівня, і чому це просто не має сенсу бути використовується на Java.


"Потік управління програмою здійснюється повністю за допомогою goto". Ну, не завжди безумовне гото.
Пітер Мортенсен

Стрибки з "goto" з однієї функції в мітку в іншій функції також не можливі в C / C ++. Перехід на C / C ++ обмежений одним функціональним блоком.
користувач2328447

"просто немає необхідності мати такі низькі функції, як goto, коли більш високі конструкції" - пам'ятайте "Необхідність і достатність". Це просто "не потрібно". І, отже, немає причин. У чому причина: "Goto" як заміна "високого рівня" для JMP-файлів, BNE та іншого тощо є розумним, якщо ви хочете перейти до "виконуваного коду", але Java є байт-кодом і, отже, не є "виконуваним". ;-)
рейххарт

10

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


9

Ні, на щастя, gotoна Java немає.

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


Чи можу я знати, що тут означало зарезервоване? Якщо використання goto і const у коді не є хорошою практикою, чому вони резервують це? Чи можете ви поясніть, будь ласка?
Гопі

@ Шрі Кумар: див. Відповідь @ applechewer, вона існує, але вона не реалізована.
Валентин Рочер

1
@Sri Kumar: Зарезервовані ключові слова не дозволяють використовувати їх як імена змінних або подібні. Таким чином, ці ключові слова можуть бути реалізовані в майбутніх версіях 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

Для чого застосовується змінна «друк»? Слова, які ви згадали, більше нагадують назви методів, ніж змінні чи ключові слова.
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
@Bozho: ну, це може бути використане для якоїсь геніальної нової функції, яка абсолютно не має нічого спільного з старим поганим "шкідливим" гото.
Майкл Боргвардт

3

Зауважте, що ви можете замінити більшість доброякісних застосувань goto на

  • повернення

  • перерва

  • зламати етикетку

  • кинути всередину пробувати-нарешті


5
Винятки НІКОЛИ не повинні використовуватися для контролю потоку
ChssPly76,

13
Винятки будуть використовуватися для управління потоком, але їх слід використовувати тільки у виняткових випадках. Наприклад, одним із застосувань goto в C є керування помилками, особливо якщо це стосується очищення.
starblue

2
@starblue, ти вийняв слова з моїх уст. Викиданням винятку є контрольний потік. В C, насправді, ви можете дещо чисто реалізувати обробку винятків через setjmp / longjmp, переконавшись, що спочатку встановите код обробки та виконайте longjmp () з ним виключення.

Я хочу зробити, якщо перевірити, і пропустити половину методу, якщо це правда. Без їзди я повинен користуватися гігантом ще. IMO це дуже некрасиво, оскільки занадто багато парантезів створює плутанину
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 в байт-коді не означає, що в java є goto, оскільки "in java" означає "In java language", а байт-код не є шаром джерела.

@ tgm1024, "на Java" також можна інтерпретувати як "на платформі Java". Компілятору Java необхідно створити байт-код або вихідний код Java не працюватимуть на платформі Java JVM. Наприклад, C ++ не визначає висновок компіляції, і компілятор вільний створювати будь-яку форму машинного коду (або будь-який інший код). Запрограмований байт-код програми Java може називатися "додатком Java", але програмований програмним кодом додаток не можна назвати "додатком C ++".
Mikael Lindlöf

2
Я добре знаю, що таке байт-код Java. Я вперше кодував Java в 1996 році. І ви можете мати інші мови для створення байт-коду Java для JVM. Де я вас виправляю, є ця ідея, що є два шари джерела. Там нема. У вас є джерело java, і це компілюється в байт-код Java (виконується JVM), і це не є додатковим шаром джерела. Тільки тому, що в байтовому коді є "goto", це не означає, що в Java є "goto". Java назвала перерви, а ім'я продовжується, але немає goto.

@ tgm1024 Мене прокинуло протистояння :) Легко здається, що я програв аргумент, оскільки ви зробили останній коментар, і ваші повноваження вражають. Моя думка, яку я будував, - це те, що програмувати за допомогою байт-коду Java дуже можливо. Для того, щоб запевнити вас, тут навіть питання про те , що: stackoverflow.com/questions/3150254 / ...
Мікаел Lindlöf


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

(Отже, ви в основному пишете VM, який виконує ваш двійковий код ... де line відповідає покажчику інструкції)

Це набагато читабельніше, ніж використовує код goto, чи не так?


Наступне запитання: "Чи є у Python заява про перемикання"
Марк К Коуан

0

Звичайно, це ключове слово, але воно не використовується на рівні вихідного коду.

Але якщо ви використовуєте жасмін або іншу мову нижчого рівня, яка перетворюється на байт-код, то "goto" є


-1

Тому що, хоча мова Java не використовує його, байт-код JVM так і є.


7
Тоді чому в мові немає loadключового слова?
Наближається до

3
@gribnit, перехід на байт-код сам по собі не означає нічого для зарезервованих слів верхнього рівня.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.