Java中有goto语句吗?


259

我对此感到困惑。我们大多数人都被告知Java中没有任何goto语句。

但是我发现它是Java中的关键字之一。在哪里可以使用?如果不能使用它,为什么将它作为关键字包含在Java中?


13
提示:永远不要使用goto
Lostiniceland

16
然后是“'发表声明认为有害'被认为有害”,以及''''发表声明认为有害”被认为有害'被认为有害吗?” VEEEEERY递归,此模因。
克里斯·查拉巴鲁克

70
“ goto”总是邪恶的-就像在“ goto work”或“ goto school”中一样;)
Andreas Dolk,2009年

24
真正的原因是“ g ** o”一词在大多数编程语言中都被认为是淫秽的。Java设计师只是在保护无辜的年轻程序员不受腐败影响。(:
Stephen C

25
反对goto的女巫狩猎催生了我一生中最痛苦的时刻。我见过人们通过隐藏函数中的功能来扭曲C代码,将荒谬的退出逻辑放在多嵌套循环中,或者以其他方式过度设计可以想象的形式,以避免有人在代码审查中批评他们的代码。毫无疑问,这条规则与“你必须避免多次退货”相提并论。有时候goto会使事情变得难以维护。有时goto使事情变得更容易维护。我真希望这场追捕女巫会在80年代死掉。

Answers:


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.实际上,主要原因是有点不同(请参阅下面的答案)
Vitalii Fedorenko 2010年

2
那是很好的信息,但是并不能解释为什么它仍然是保留关键字。
托马斯

@Thomas您没有描述为什么要保留它吗?这是一个关键字,因此现在无法使用;以后的goto可以重生,而不会造成问题。如果不是保留字,则现在可以使用它来生成代码(int goto = 2;),如果引入goto则代码会中断。

230

James Gosling创建了带有goto语句支持的原始JVM ,但随后他将该功能移除为不必要。goto不必要的主要原因是通常可以将其替换为更具可读性的语句(如break/continue)或将一段代码提取到方法中。

资料来源:James Gosling,问答环节


24
“ ...或通过将一段代码提取到方法中”-在没有适当的尾部调用消除的情况下,它必须非常酷。
显示名称

45
有时候,明智地使用来表达goto 最容易和最清楚的方式来表达事物,因此将其强制放入其他任何事物中的行为都会使可读性降低
Deduplicator

1
@Deduplicator goto的用法(可能是明智的)始终容易出错。
切莱比穆拉特

@Deduplicator在C ++中,只有goto被认为是良好的实践,这是由break / continue支持的。

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

1
@Zoltán否-在第一个循环之前,它将代码重定向到标签。
亚述

21
@assylias好吧,不是。标签标记了外环。则break loops意味着“打破循环称为loops”。也许回想起来,这个标签可能更合适outer
jonnystoten 2012年

8
“唯一的使用goto的理由”需要无条件无限循环的快速而肮脏的小程序充分利用了goto。使用while (true) {... }是过大的。GOTO经常因使用不当而受到污名化,但我认为,对布尔文字进行不必要的比较会比GOTO糟糕。
亚历山大–恢复莫妮卡

1
循环标签不应该在循环之后吗?
GC_

1
我最近发现,这种标记技术与continue LABEL;语句结合使用也非常有用。因此,您可以继续进行外循环。
infotoni91 '18


29

因此,如果语言设计人员认为有必要,可以在一天之内使用它们。

同样,如果使用具有这些关键字(例如C,C ++)的语言的程序员错误地使用了它们,则Java编译器会给出有用的错误消息。

或者也许只是为了阻止程序员使用goto :)


Java中缺少的goto功能应该有足够的理由不使用goto-无需将其保留为关键字。遵循您的逻辑,一切都将成为关键字,因为其他语言可能会使用它,并且/或者Java设计人员将来可能会使用它……
stuXnet 2014年

1
我不认为我的逻辑暗示一切都会是关键字。在许多编程语言中使用的关键字很少,可以用Java有效地检测和处理。Java保留gotoconst反映了其C / C ++的传统,但它们仍未实现(尽管关于实现后者的争论一直存在)。有几个更像assert并且enum最初并没有保留,但是考虑到已经实现,应该保留一些。但是事后看来是一件了不起的事情。
2014年

19

它们保留供将来使用(请参阅:Java语言关键字)。

关键字const和goto被保留,即使它们当前未使用。

究其原因,为什么没有在Java中没有goto语句可以在“发现Java语言环境 ”:

Java没有goto语句。研究表明,goto被(误用)的频率不仅仅是“因为它存在”,还有更多。消除goto会导致语言的简化-例如,对于for语句的中间没有goto的影响规则。对大约100,000行C代码行的研究确定,大约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中的每个语句和函数都可以轻松地分解为汇编语言指令。尽管C并不是当今编程计算机的主要语言,但它仍大量用于底层应用程序(例如嵌入式系统)中。因为C的功能如此紧密地反映了汇编语言的功能,所以只有goto包含在C中。

显然,Java是C / C ++的发展。Java具有C语言的许多功能,但是抽象了很多细节,因此编写方式​​有所不同。Java是一种非常高级的语言,因此根本没有必要具有低级功能,例如,goto当诸如函数,for,for和while循环执行程序控制流时,就需要具有更高级的构造。想象一下,如果您处于一个功能中,并且goto将一个标签标记为另一个功能。当另一个函数返回时会发生什么?这个想法是荒谬的。

这并不一定能回答为什么Java包含该goto语句但仍不允许其编译的问题,但重要的是要知道为什么goto首先在较低级别的应用程序中使用过该语句,以及为什么这样做根本没有意义。在Java中使用。


“程序控制流程完全通过goto完成”。好吧,并非总是无条件转到。
彼得·莫滕森

在C / C ++中,也无法通过“转到”从一个功能跳转到另一功能的标签中。C / C ++中的Goto仅限于单个功能块。
user2328447 '17

“当使用更高级的结构时,根本不需要具有诸如goto之类的低级功能”-记住“必要性和充分性”。只是“没有必要”。因此没有理由。原因是什么:如果要跳转到“可执行代码”,而Java是字节码,因此不是“可执行文件”,那么“ Goto”作为汇编器的JMP,BNE等的“高级”替代是合理的。;-)
reichhart


9

不,值得庆幸的是goto,Java中没有。

goto关键字仅保留,但不使用(也是如此const)。


我可以知道保留的意思是什么吗?如果在代码中使用goto和const不是一个好习惯,为什么他们保留它?你能解释一下吗?
Gopi 2010年

@Sri Kumar:请参阅@applechewer的答案,它存在但未实现。
Valentin Rocher 2010年

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的变量或方法?
Michael Borgwardt 2009年

4
因为它在编程领域中具有不适用于Java的含义。这也是变量名称的不佳选择。
pjp

变量“ print”将用于什么?您提到的单词更像是方法名称,而不是变量或关键字。
pjp

3
-1:首先,仅因为Java不支持“ goto”流控制语句,并不意味着这就是它具有不执行任何操作的“ goto”关键字的原因。其次,“ goto”可能是一个不好的变量名,但它可能是一个出色的方法名,因为“ goto”是一个关键字,所以我们不能使用它。第三,“中断标签”和“继续标签”的存在是有充分理由的,因此“不推荐使用”并不是很有用。第四,由于Sun表示“当前未使用”,这很可能意味着他们曾经计划实施,但是在他们决定不这样做时,并不想摆脱该关键字。
Vojislav Stojkovic 2010年

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 2014年

7

不,goto尽管是保留字,但在Java中未使用。的情况也是如此const。这两个都是在C ++中使用的,这可能是保留它们的原因。这样做的目的可能是避免使C ++程序员迁移到Java时造成混淆,并且还可能保留在更高版本的Java中使用它们的选择。


1
我真的希望goto至少在不久的将来不会得到支持;)
博若

6
@Bozho:好吧,它可以用于某些新颖的新功能,该功能与糟糕的旧“有害” goto绝对无关。
Michael Borgwardt 2010年

3

请注意,您可以通过以下方式替换goto的大部分良性用途:

  • 返回

  • 打破

  • 打破标签

  • 最终放入try-catch-find


5
切勿将异常用于流量控制
ChssPly76

13
例外用于流量控制,但仅用于特殊情况下,应使用。例如,C语言中goto的用途之一是错误处理,尤其是在涉及清理时。
starblue

2
@starblue,您从我口中说出了这些话。抛出异常控制流。实际上,在C语言中,可以通过确保首先将setjmp设置为处理代码并在异常上对其执行longjmp()来通过setjmp / longjmp干净地实现异常处理。

我想做一个if检查,如果为true则跳过方法的一半。不去我必须用其他巨人。海事组织(IMO)这非常丑陋,因为太多的
寄生物

1
@WVrock您可以尝试return
Andrew Lazarus

2

如前所述goto,Java中没有,但是保留了关键字,以防Sun goto有一天想添加到Java中。他们希望能够在不破坏太多代码的情况下添加它,因此他们保留了关键字。请注意,对于Java 5,他们添加了enum关键字,它也不会破坏太多的代码。

尽管Java没有goto,但它具有一些对应于的某些用法的构造goto,即能够使用命名循环breakcontinue使用命名循环。另外,finally也可以认为是一种扭曲goto


1

禁止声明相同名称的变量。

例如 int i = 0, goto;


3
但是为什么呢?为什么我们不应该被允许发表这些声明?
2014年

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 ++应用程序”。
MikaelLindlöf,2015年

2
我完全知道什么是Java字节码。我于1996年首次使用Java进行编码。您可以让其他语言为JVM生成Java字节码。我要纠正的是这个想法,它包含两层源。没有。您有Java源代码,它被编译为Java字节码(由JVM执行),并且这不是源代码的附加层。仅仅因为字节码中有一个“ goto”并不意味着在Java中就有了“ goto”。Java已命名中断,并命名为continue,但没有goto。

@ tgm1024我被选票惊醒了:)因为您发表了最后的评论,而且您的证书给人留下深刻的印象,我似乎很容易就失去了论点。我要强调的一点是,使用Java字节码进行编程非常有可能。:为了保证您,这里甚至有一个关于这个问题stackoverflow.com/questions/3150254/...
的MikaelLindlö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中是否有switch语句”
Mark K Cowan,

0

当然,它是关键字,但未在源代码级别上使用。

但是,如果您使用jasmin或其他较低级别的语言(已转换为字节码),则存在“ goto”


-1

因为尽管Java语言未使用它,但JVM字节码却使用了它。


7
那为什么语言没有load关键字呢?
2014年

3
@gribnit,在字节码中具有goto本身并不意味着高级保留字。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.