文章目录
前言
goto语句是在源码级上的跳转,这使得其招致了不好的声誉。Dijkstra发表了著名论文《Goto considered harmful》(goto有害)若一个程序总是从一个地方跳到另一个地方,那么还有什么办法能识别程序的流程控制呢?
一、goto是什么?
goto起源于汇编语言的程序控制:“若条件A允许,则跳进这里;否则跳到那里”。如果阅读由编译器最终生成的汇编代码,就会发现程序控制里面包含了许多跳转。(Java编译器生成他自己的“汇编代码”,但是这个代码是运行在Java虚拟机上的,而不是在CPU硬件上的。)
二、goto与Java的关系
1.关系
尽管在Java中有goto这个保留字,但在语言中却用不到它。Java没有goto,但是Java也能完成一些类似于跳转的操作,这与break和continue用法有关。总所周知,他们并不是一个跳转,而是中断迭代语句的一种方法。能够与goto相提并论的关键在于,这二者与goto有相同的机制——标签
2.Java中的标签
标签:后面带有冒号的标识符 例: label:
在Java中,标签起作用的唯一地方恰好是在迭代语言之前。这句话的意思是:在标签和迭代之间置入任何语句都是不好的。而在迭代之前设置标签的唯一理由就是:我们希望在其中一个嵌套另一个迭代或者开关。
3.break和continue的进阶用法(即结合标签)
1.代码如下(示例):
label1:
outer-iteration{
inner-iteration{
//...
continue; (1)使执行点移回到内部迭代的起始处
//...
break; (2)中断内部迭代,回到外部迭代
//...
continue label1; (3)同时中断内部迭代和外部迭代,直接转到label1处
//...
break label1; (4)同3
}
}
从上我们能注意到(3)(4)均能跳到标签处,值得注意的是label1后面不能添加任何语句
2.下面这个例子我们将更加清楚continue和break带标签的区别
public class Draft_07 {
public static void main(String[] args) {
int i = 0;
outer:
while(true){
System.out.println("outer while loop");
while(true){
i++;
System.out.println("i = "+i);
if (i == 1){
System.out.println("continue");
continue;
}
if (i == 3){
System.out.println("continue outer");
continue outer;
}
if (i == 5){
System.out.println("break");
break;
}
if (i == 7){
System.out.println("break outer");
break outer;
}
}
}
}
}
我们会发现二者具体的区别
a.带标签的continue会到达标签的位置,并重新进入紧接在那个标签后的循环。
b.带标签的break会中断并跳出标签所指的循环。
要记住的重点是,在Java中唯一要使用标签的理由就是因为有嵌套循环的存在,而且是想从多层嵌套中break或continue
总结
《Goto considered harmful》(goto有害)论文中最反对的其实是标签而不是goto,因为实践证明程序随着标签的增加而产生的错误增加,且不利于程序的分析。但在Java由于标签的应用场合受到限制并不会引起这种问题,正如Java编程思想一书中所言的一个现象,通过限制语言的能力,反而能使一项语言特性变得更加有用。