1、break和continue
在任何迭代语句的主体部分,都可用break和continue控制循环的流程。其中,break用于强行退出循环,不执行循环中剩余的语句。而continue则停止执行当前的迭代,然后退回循环起始处,开始下一次迭代。
无穷循环的两种形式:while(true) 和 for(;;)。
2、臭名昭著的goto
编程语言中一开始就有goto关键词了,事实上,goto起源于汇编语言的程序控制;“若条件A成立,则跳到这里;否则跳到那里”。如果阅读由编译器最终生成的汇编代码,就会发现程序控制里包含了许多跳转。(JAVA编译器生成它自己的“汇编代码”,但是这个代码是运行在Java虚拟机上的,而不是直接运行在CPU硬件上。)
goto语句是在源码级上的跳转,这使其招致了不好的声誉。
尽管goto仍是Java中的一个保留字,但在语言中并未使用它;Java没有goto。然而,Java也能完成一些类似于跳转的操作,这与break和continue这两个关键词有关。它们其实不是一个跳转,而是中断迭代语句的一种方法。之所以把它们纳入goto问题中一起讨论,是由于它们使用了相同的机制:标签。
标签是后面跟有冒号的标识符,就像:label1:
在Java中,标签起作用的唯一的地方刚好是在迭代语句之前。”刚好之前“的意思表明,在标签和迭代之间置入任何语句都不好。而在迭代之前设置标签的唯一理由是:我们希望在其中嵌套另一个迭代或者一个开关。这是由于break和continue关键词通常只中断当前循环,但若随同标签一起使用,它们就会中断循环,直到标签所在的地方:
label1:
outer-iteration{
inner-iteration{
//...
break; //(1)
//...
continue; //(2)
//...
continue label1; //(3)
//...
break label1; //(4)
}
}
在(1)中,break中断内部迭代,回到外部迭代。在(2)中,continue 使执行点移回内部迭代的起始处。在(3)中,continue label1同时中断内部迭代以及外部迭代,直接转到label1处;随后,它实际上是继续迭代过程,但却从外部迭代开始。在(4)中,break label1也会中断所有迭代,并回到label1处,但并不重新进入迭代。也就是说,它实际是完全中止了两个迭代。
如果想在中断循环的同时退出,简单的用一个return即可。
同样的规则也适用于while:
(1)一般的continue会退回最内层循环的开头(顶部),并继续执行。
(2)带标签的continue会到达标签的位置,并重新进入紧接在那个标签后面的循环。
(3)一般的break会中断并跳出当前循环。
(4)带标签的break会中断并跳出标签所指的循环。
要记住的重点是:在Java里需要使用标签的唯一理由就是因为由循环嵌套存在,而且想从多层嵌套中break或continue。