break语句除了与switch语句和循环语句一起使用之外,也可以作为一种“文明”的goto语句单独使用。Java没有goto语句,因为该语句提供的是改变程序执行流程的非结构化的方法。大量使用goto语句的程序通常难以理解,难以维护。然而,在有些地方goto语句却是合理有用的。例如,goto语句在从嵌套很深的循环退出时就很有用。为处理这些情况,Java定义了break语句的一种扩展形式。通过使用这种形式的break语句,可以从一个或多个代码块中退出。这些代码块不需要是循环或switch语句的一部分。他们可以是任何代码块。不仅如此,还可以精确的指定执行流继续执行的位置,因为这种形式的语句在工作时有一个标记。如你所见,break语句只为你提供goto语句的优点,却不会带来goto语句产生的问题。
带有标记的break语句的基本形式如下所示:
break label;
这里,label用于标识代码块的标记名。当这种break语句执行时,控制权就会转移到代码块外。已标记的代码块必须包含break语句,但不必立刻结束代码块。这就意味着可以使用带标记的break语句从一系列嵌套代码块中退出。然而,不能使用break语句把控制权转移到另一个不包含break语句的代码块。
要命名一个代码块,只需要在他的前面加标记就可以。被标记的代码块可以是单独的代码块,也可以是以代码块作为目标的语句。label可以是任何后面跟有冒号的有效的java标识符。一旦对一个代码块进行了标记,就可以把这个标记作为break语句的目标。这样做会使执行流在已标记的结尾继续执行。
public static void main(String[] args) throws java.io.IOException { int i; for(i=1;i<4;i++) { one: { two: { three: { if(i == 1) break one; if(i == 2) break two; if(i == 3) break three; } System.out.println("after block three i="+i); } System.out.println("after block two i="+i); } System.out.println("after block one i="+i); } }
输出:
after block one i=1 after block two i=2 after block one i=2 after block three i=3 after block two i=3 after block one i=3
仔细研究程序,以便弄明白这个结果是如何产生的。当i为1时,第一个if语句成立,这使得控制权转移到标记one定义的代码块的结尾,输出“atfer block one”,当i为2时,第二个if成立,使得控制权转移到标记two定义的代码块的结尾,输出消息“after block two”和“after block one”,当i等于3时,控制将转移到标记three定义的代码块结尾,这时就会显示所有三条消息。
问:你说goto是非结构化的,而带有标记的break语句提供了一种更好的方式,但是使用break中断并跳转到许多行和嵌套层之外不也是一种非结构化的方法吗?
答:简言之,的确如此。但是在程序的执行流需要跳转的情况下,跳转到标记还可以保留一些结构化特性,而使用goto则不能。