Java 中break和continue结合标签标示符中断循环示例详解(附源码)
Posted mufeng_慕枫
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 中break和continue结合标签标示符中断循环示例详解(附源码)相关的知识,希望对你有一定的参考价值。
臭名昭著的goto
编程语言中一开始就有goto关键词了。事实上,goto起源于汇编语言的程序控制:“若条件A成立,则跳到这里;否则跳到那里”。如果阅读由编译器最终生成的汇编代码,就会发现程序控制里包含了许多跳转。(Java编译器生成它自己的“汇编代码”,但是这个代码是运行在Java虚拟机上的,而不是直接运行在CPU硬件上。)
goto语句是在源码级上的跳转,这使其招致了不好的声誉。若一个程序总是从一个地方跳到另一个地方,还有什么办法能识别程序的控制流程呢?自从Edsger Dijkstra发表了著名论文《Goto considered harmful》(Goto有害),众人开始痛斥goto的不是,甚至建议将它从关键字集合中扫地出门。
对于这个问题,中庸之道是最好解决方法。真正的问题并不在于使用goto,而在于goto的滥用;而且少数情况下,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处,但并不重新进入迭代。也就是说,它实际是完全中止了两个迭代。
示例源码
下面是标签用于for循环和while循环的例子:package com.mufeng.thefourthchapter; public class Labeled { public static void main(String[] args) { System.out.println("标签用于for循环的例子"); int i = 0; outer: // Can't have statements here 这里不能有陈述 for (; true;) {// infinite loop 无限循环 inner: // Can't have statements here 这里不能有陈述 for (; i < 10; i++) { System.out.println("i = " + i); if (i == 2) { System.out.println("continue"); continue; } if (i == 3) { System.out.println("break"); i++;// Otherwise i never gets incremented 否则i不会得到增量 break; } if (i == 7) { System.out.println("continue outer"); i++;// Otherwise i never gets incremented 否则i不会得到增量 continue outer; } if (i == 8) { System.out.println("break outer"); break outer; } for (int k = 0; k < 5; k++) { if (k == 3) { System.out.println("continue inner"); continue inner; } } } } System.out.println("标签用于while循环的例子"); 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; } } } } }
输出结果
标签用于for循环的例子 i = 0 continue inner i = 1 continue inner i = 2 continue i = 3 break i = 4 continue inner i = 5 continue inner i = 6 continue inner i = 7 continue outer i = 8 break outer 标签用于while循环的例子 Outer while loop i = 1 continue i = 2 i = 3 continue outer Outer while loop i = 4 i = 5 break Outer while loop i = 6 i = 7 break outer
源码解析
注意,break会中断for循环,而且在抵达for循环的末尾之前,递增表达式不会执行。由于break跳过了递增表达式,所以在i==3的情况下直接对i执行递增运算。在i==7的情况下,continue outer语句会跳到循环顶部,而且也会跳过递增,所以这里也对i直接递增。
如果没有break outer语句,就没办法从内部循环里跳出外部循环。这是由于break本身只能中断最内层的循环(continue同样也是如此)。
当然,如果想在中断循环的同时退出,简单地用一个return即可。
同样的规则亦适用于while:
- 一般的continue会退回最内层循环的开头(顶部),并继续执行。
- 带有标签的continue会到达标签的位置,并重新进入紧接在那个标签后面的循环。
- 一般的break会中断并跳出当前循环。
- 带标签的break会中断并跳出标签所指的循环。
要记住的重点是:在Java里需要使用标签的唯一理由就是因为有循环嵌套存在,而且想从多层嵌套中break或continue。
以上是关于Java 中break和continue结合标签标示符中断循环示例详解(附源码)的主要内容,如果未能解决你的问题,请参考以下文章