带标签的 break 和 continue (Java)

2002年12月发于 CCW-I
2006年9月搬至 CSDN,略作修改

  Java 中有 goto 关键字,但这个关键字没有任何作用,换句话说,我们不能使用 goto 来进行跳转到某行。实际上,结构化程序设计完全不需要 goto 语句即可完成各种流程,而 goto 语句的使用往往会使程序的可读性降低,所以 Java 不允许 goto 跳转。

  Java 中同样可以定义标签,使用标识符加冒号 (:) 的形式,如“mylabel:”。不过既然 Java 中的 goto 没有实质性的作用,标签的设计当然就不是为了 goto。

  Java 中的标签是为循环设计的,是为了在多重循环中方便的使用 break 和 coutinue 而设计的。正是由于这个原因,Java 的标签只能定义在三种循环 (for() {}, do{} while(), while() {}) 的开始位置,否则编译器会报告说找不到标签。稍后的例子即可更直观的说明。

  在循环前面加上标签,就好像给循环起了个名字。而后在循环中使用 break 或者 continue 语句的时候,就可以带上这个标签做为参数,指明跳出 (break) 或者继续 (continue) 哪一个循环,如“break mylabel;”、“continue mylabel;”。现在请看下面的例 1,直观的了解标签的用法,其中的注释已经大略说明了每分部代码在干什么,而示例后面的解释会让你更加明白:

  例 1:LabelExmaple.java

/*
 * @(#) LabelExample.java
 * @author James Fancy
 */

/**
 * LabelExample 类将随机生成一个二维数组,
 * 数组每一行中的数据都是从小到在的顺序排列,但各行间并没有排序。
 * 同时,LabelExample 还会从生成的二维数组里随机找一个数作为要查找的数据。
 * 随后在 search 方法中使用带标签的 break 和 continue 语句来优化查找代码。
 */
public class LabelExample {

    /**
     * 主程序。
     */
    public static void main(String[] args) {
        LabelExample test = new LabelExample(3, 5);
        test.printMatrix();
        System.out.println();
        test.search();
    }

    int row; // 二维数组的行数

    int col; // 二维数组每行的数据个数

    int[][] data; // 数组数据

    int lookfor; // 要在数组中查找的数

    /**
     * 构造函数,生成一个由 row 指定行数,由 col 指定列数的数组。
     */
    public LabelExample(int row, int col) {
        this.row = row;
        this.col = col;
        createMatrix();
    }

    /**
     * 打印数组内容。
     */
    public void printMatrix() {
        System.out.println("row = " + row + ", col = " + col + ", lookfor = "
                + lookfor);
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                System.out.print(" " + data[i][j]);
            }
            System.out.println();
        }
    }

    /**
     * 演示查找过程,使用带标签的 break 和 continue 语句。
     */
    public void search() {
        //loop1:
        // 若在此处定义标签,由于不是其后紧跟循环语句,所以会被勿略掉。
        // 被忽略掉的标签,如果在 break 或者 continue 语句中用到,编译时不能通过。
        // 如果没有在 break 或者 continue 中用到则编译可以成功。
        System.out.println("--- Begin Searching ---");
        loop1: for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (data[i][j] > lookfor) {
                    System.out.println("--- JUMP ---");
                    continue loop1; // 想想此处用 break,结果会有什么变化
                }
                if (data[i][j] == lookfor) {
                    System.out.println("FOUND: data[" + i + "][" + j + "] = "
                            + lookfor);
                    break loop1; // 想想此处用 return,结果会有什么变化
                }
                System.out
                        .println("data[" + i + "][" + j + "] = " + data[i][j]);
            }
            System.out.println("--- LOOP2END ---");
        }
        System.out.println("--- End Searching ---");
    }

    /**
     * 生成随机数组和随机抽取要查找的数。
     */
    private void createMatrix() {
        data = new int[row][];
        for (int i = 0; i < row; i++) {
            data[i] = new int[col];
            int t = 0;
            for (int j = 0; j < col; j++) {
                t += (int) (Math.random() * 20);
                data[i][j] = t;
            }
        }
        lookfor = data[(int) (Math.random() * row)][(int) (Math.random() * col)];
    }

}

  这段程序的运行结果如下:

row = 3, col = 5, lookfor = 48
    11  21  22  38  39
    14  22  40  55  72
    11  29  38  48  63

--- Begin Searching ---
data[0][0] = 11
data[0][1] = 21
data[0][2] = 22
data[0][3] = 38
data[0][4] = 39
--- LOOP2END ---
data[1][0] = 14
data[1][1] = 22
data[1][2] = 40
--- JUMP ---
data[2][0] = 11
data[2][1] = 29
data[2][2] = 38
FOUND: data[2][3] = 48
--- End Searching ---

  由于程序中所有数据都是随机生成的,所以,运行该程序多次才得到上述较具代表性的结果。

  上面程序中,createMatrix 方法和 printMatrix 方法都是工具,一个用于初始化数据,另一个则用于打印数组。而另一个方法 search 则是演示程序的关键之所在。

  search 方法中打印的数据足以说明查找的过程。第一个 for 循环 (即标签为 loop1 的那个) 用于遍历二维数组中的所有组 (即每一行);第二个 for 循环嵌套在第一个 for 循环中,用来遍历每一组中的所有数据,以便依次查找。

  如果第二个 for 循环对某组数据进行查找的过程中没有找到要查找的数据,则有两种情况:1) 该组的数据全都比要查找的数据小,那么这个循环能够被完整执行,则可以执行该循环之后的语句,即输出“--- LOOP2END ---”。2) 该组数据有比要查找的数据大的数据,那么在检查到第一个比要查找的数据大的数据时,执行了 continue loop1。此语句不仅跳出了第二个 for 循环,还中止了第一个 for 循环中尚未执行的语句,直接进行第一个 for 循环的下一次循环。这里有一个问题,如果把 continue loop1 改成 break 会怎么样呢?如果改了,输入结果就会是:

……
--- JUMP ---
--- LOOP2END ---
  ……
  造成这一现象的原因,是 braek 只中止了第二个循环,却没有中止第一个循环中尚未执行的语句。

  现在在来看看找到了目标数据时的情况。如果找到了目标数据,则无论再执行哪一个循环都毫无意义了。所以,要中止掉两个循环。由于是在第二个循环中找到数据的,而第二个循环嵌套在第一个循环当中,如果直接 break 的话,则只能中止第二个循环,第一个循环仍然会继续;而使用 break loop1 则指定了中止第一个循环,既然第一个循环都被中止了,那么依赖于第一个循环的第二个循环当然也就被中止了。这里也有一个问题,为什么不用 return 呢?我想这个问题比上一个问题更好答,因为如果使用 return,那么这两个 for 循环之后的语句怎么办?

  需要注意的是,这里的 continue 和 break 都用到了 loop1 标签。如果将代码中“System.out.println("--- Begin Searching ---");”和“loop1:”两条语句的位置交换一下,那么结果会怎么样呢?此时编译器会报告说找不到 loop1 标签。这就是上面提到的,标签定义之后必须紧接着循环语句的原因。不过,如果程序中没有任何一个 break 或者 continue 语句用到 loop1 的话,就无所谓 loop1 定义在哪里了,编译器会把它忽略掉的。

  最后,补充一句,一般情况下还是不要使用 label。如果遇到一些比较复杂的多重循环,我更愿意建议使用多个方法来执行每一层的循环,这样会让程序结构显得更加清楚一些。

时间: 2024-08-01 10:46:10

带标签的 break 和 continue (Java)的相关文章

带标签的break和continue语句 *寻找100~150之间的质数*

1 //比较break和continue语句的不同 2 public class TestBreakContinue { 3 public static void main(String[] args){ 4 int a = 0; 5 System.out.println("Begin"); 6 while(true){ 7 a++; 8 int b = (int)Math.round(100*Math.random()); 9 if(b==88)break; 10 } 11 Syst

JavaScript -- 标签 , Break 和 Continue 语句

break 语句用于跳出循环. continue 用于跳过循环中的一个迭代. 标签引用,break 语句可用于跳出任何 JavaScript 代码块. demo: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>break Continue语句</title> </head> <body> <p>点击按钮,测

break、continue关键字配合标签使用,实现跳转功能

知识点:continue和break配合标签实现跳转功能 尽管java中goto是一个保留字,但在语言中并未使用它,Java没有goto.然后java也可以完成一些类似于跳转的操作,那就是将break和continue配合标签一起使用 标签是后面跟有冒号的标识符,就像下面这样: lable1: 在java中,标签起作用的唯一地方刚好是在迭代语句之前."刚好之前"的意思表明,在标签和迭代之间置入任何语句都不好.而在迭代之前设置标签的唯一理由是:我们希望在其中嵌套另一个迭代或者一个开关.这

Java 中break和continue结合标签标示符中断循环示例详解(附源码)

臭名昭著的goto 编程语言中一开始就有goto关键词了.事实上,goto起源于汇编语言的程序控制:"若条件A成立,则跳到这里:否则跳到那里".如果阅读由编译器最终生成的汇编代码,就会发现程序控制里包含了许多跳转.(Java编译器生成它自己的"汇编代码",但是这个代码是运行在Java虚拟机上的,而不是直接运行在CPU硬件上.) goto语句是在源码级上的跳转,这使其招致了不好的声誉.若一个程序总是从一个地方跳到另一个地方,还有什么办法能识别程序的控制流程呢?自从Ed

Java中break和continue跳出指定循环

在Java中,break和continue可以跳出指定循环,在循环前指定一个标签名称,使用break跳出即可.continue同. 代码如下: (1) 简单的一个continue会退回最内层循环的开头(顶部),并继续执行.        (2) 带有标签的continue会到达标签的位置,并重新进入紧接在那个标签后面的循环 (3) break会中断当前循环,并移离当前标签的末尾. (4) 带标签的break会中断当前循环,并移离由那个标签指示的循环的末尾. 扩展: Java中,goto语句作为保

Java中的break和continue关键字使用总结

一.作用和区别 break的作用是跳出当前循环块(for.while.do while)或程序块(switch).在循环块中的作用是跳出当前正在循环的循环体.在程序块中的作用是中断和下一个case条件的比较. continue用于结束循环体中其后语句的执行,并跳回循环程序块的开头执行下一次循环,而不是立刻循环体. 二.其他用途 break和continue可以配合语句标签使用.这个都很简单,下面给个综合实例,看看就明白 了: /** * Created by IntelliJ IDEA. * U

Java中的break和continue以及标签

一.Java中的break,continue,goto 首先break,continue是Java中的关键字,而goto是保留字. 基于goto在c和c++中的鬼畜表现,我觉得goto可能还会长期在Java中坐冷板凳. break:强行退出循环,不执行循环中的后续步骤. continue:推出当前的循环,回到循环的起始点,开始一次新的循环 例子如下: // continue System.out.println("//continue:"); for (int i = 0; i <

java中break、continue及标签等跳转语句的使用[上]

java 中跳转语句使用break.continue和标签,各自或组合完成相应的功能. 今天做题时遇到关于标签命名规范,顺便将跳转语句语法都看了一遍,很有收获. 在<Java编程思想>一书中,作者详细阐述,现将案例代码写在下面: public class LabeledFor { public static void main(String[] args) { int i=0; outer: for(;true;){ inner: for(;i<10;i++){ System.out.p

Java SE之break和continue标签

文是学习网络上的文章时的总结,感谢大家无私的分享. Java没有提供goto功能,可是保留了gotokeyword. 在java中能够使用break标签和continue标签功能实现简版的goto功能. 以下的小代码做抛砖引玉. package SE; /** * * <p> * Description: 使用break和continue的标签功能 * </p> * @author zhangjunshuai * @version 1.0 * Create Date: 2014-1