3.8.6 中断控制流程语句
尽管Java的设计者将goto作为保留字,但实际上并没有打算在语言中使用它。通常,使用goto语句被认为是一种拙劣的程序设计风格。当然,也有一些程序员认为反对goto的呼声似乎有些过分(例如,Donald Knuth就曾编著过一篇名为《Structured Programming with goto statements》的著名文章)。这篇文章说:无限制地使用goto语句确实是导致错误的根源,但在有些情况下,偶尔使用goto跳出循环还是有益处的。Java设计者同意这种看法,甚至在Java语言中增加了一条带标签的break,以此来支持这种程序设计风格。
下面首先看一下不带标签的break语句。与用于退出switch语句的break语句一样,它也可以用于退出循环语句。例如,
在循环开始时,如果years>100,或者在循环体中balance≥goal,则退出循环语句。当然,也可以在不使用break的情况下计算years的值,如下所示:
但是需要注意,在这个版本中,检测了两次balance<goal。为了避免重复检测,有些程序员更加偏爱使用break语句。
与C++不同,Java还提供了一种带标签的break语句,用于跳出多重嵌套的循环语句。有时候,在嵌套很深的循环语句中会发生一些不可预料的事情。此时可能更加希望跳到嵌套的所有循环语句之外。通过添加一些额外的条件判断实现各层循环的检测很不方便。
这里有一个示例说明了break语句的工作状态。请注意,标签必须放在希望跳出的最外层循环之前,并且必须紧跟一个冒号。
如果输入有误,通过执行带标签的break跳转到带标签的语句块末尾。对于任何使用break语句的代码都需要检测循环是正常结束,还是由break跳出。
注释:事实上,可以将标签应用到任何语句中,甚至可以应用到if语句或者块语句中,如下所示:
因此,如果希望使用一条goto语句,并将一个标签放在想要跳到的语句块之前,就可以使用break语句!当然,并不提倡使用这种方式。另外需要注意,只能跳出语句块,而不能跳入语句块。
最后,还有一个continue语句。与break语句一样,它将中断正常的控制流程。continue语句将控制转移到最内层循环的首部。例如:
如果n<0,则continue语句越过了当前循环体的剩余部分,立刻跳到循环首部。
如果将continue语句用于for循环中,就可以跳到for循环的“更新”部分。例如,下面这个循环:
如果n<0,则continue语句跳到count++语句。
还有一种带标签的continue语句,将跳到与标签匹配的循环首部。
提示:许多程序员容易混淆break和continue语句。这些语句完全是可选的,即不使用它们也可以表达同样的逻辑含义。在本书中,将不使用break和continue。